Create column retrived from stored procedure.
namespace Serene.BasicSamples.Columns
{
using Serenity.ComponentModel;
using System;
[ColumnsScript("BasicSamples.CustomerGrossSales")]
[BasedOnRow(typeof(Northwind.Entities.CustomerGrossSalesRow))]
public class CustomerGrossSalesColumns
{
[Width(150), SortOrder(1)]
public String ContactName { get; set; }
[Width(250)]
public String ProductName { get; set; }
[Width(150), AlignRight, SortOrder(2, descending: true), DisplayFormat("#,##0.00")]
public Decimal GrossAmount { get; set; }
}
}
Create list request for passing parameter to stored procedure.
namespace Serene.BasicSamples
{
using Serenity.Services;
using System;
public class CustomerGrossSalesListRequest : ListRequest
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
}
Creat endpoint.
namespace Serene.BasicSamples.Endpoints
{
using Serenity.Data;
using Serenity.Reporting;
using Serenity.Services;
using Serenity.Web;
using System;
using System.Data;
using System.Web.Mvc;
using MyRepository = Repositories.CustomerGrossSalesRepository;
using MyRow = Northwind.Entities.CustomerGrossSalesRow;
[RoutePrefix("Services/BasicSamples/CustomerGrossSales"), Route("{action}")]
[ConnectionKey(typeof(MyRow)), ServiceAuthorize(typeof(MyRow))]
public class CustomerGrossSalesController : ServiceEndpoint
{
public ListResponse<MyRow> List(IDbConnection connection, CustomerGrossSalesListRequest request)
{
return new MyRepository().List(connection, request);
}
public FileContentResult ListExcel(IDbConnection connection, CustomerGrossSalesListRequest request)
{
var data = List(connection, request).Entities;
var report = new DynamicDataReport(data, request.IncludeColumns, typeof(Columns.CustomerGrossSalesColumns));
var bytes = new ReportRepository().Render(report);
return ExcelContentResult.Create(bytes, "CustomerGrossSales_" +
DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx");
}
}
}
create repository.
namespace Serene.BasicSamples.Repositories
{
using Serenity.Data;
using Serenity.Services;
using System.Collections.Generic;
using System.Data;
using MyRow = Northwind.Entities.CustomerGrossSalesRow;
public class CustomerGrossSalesRepository
{
private static MyRow.RowFields fld { get { return MyRow.Fields; } }
public ListResponse<MyRow> List(IDbConnection connection,
CustomerGrossSalesListRequest request)
{
var data = connection.Query<MyRow>("CustomerGrossSales",
param: new
{
startDate = request.StartDate,
endDate = request.EndDate
},
commandType: System.Data.CommandType.StoredProcedure);
var response = new ListResponse<MyRow>();
response.Entities = (List<MyRow>)data;
return response;
}
}
}
create grid.ts
namespace Serene.BasicSamples {
@Serenity.Decorators.registerClass()
export class CustomerGrossSalesGrid extends Serenity.EntityGrid<Northwind.CustomerGrossSalesRow, any> {
protected getColumnsKey() { return "BasicSamples.CustomerGrossSales"; }
protected getIdProperty() { return "__id"; }
protected getNameProperty() { return Northwind.CustomerGrossSalesRow.nameProperty; }
protected getLocalTextPrefix() { return Northwind.CustomerGrossSalesRow.localTextPrefix; }
protected getService() { return CustomerGrossSalesService.baseUrl; }
private nextId = 1;
constructor(container: JQuery) {
super(container);
}
/**
* This method is called to preprocess data returned from the list service
*/
protected onViewProcessData(response: Serenity.ListResponse<Northwind.SalesByCategoryRow>) {
response = super.onViewProcessData(response);
// there is no __id property in CustomerGrossSalesRow but
// this is javascript and we can set any property of an object
for (var x of response.Entities) {
(x as any).__id = this.nextId++;
}
return response;
}
protected getButtons() {
var buttons = [];
buttons.push(Common.ExcelExportHelper.createToolButton({
grid: this,
service: CustomerGrossSalesService.baseUrl + '/ListExcel',
onViewSubmit: () => this.onViewSubmit(),
separator: true
}));
buttons.push(Common.PdfExportHelper.createToolButton({
grid: this,
onViewSubmit: () => this.onViewSubmit()
}));
return buttons;
}
protected createSlickGrid() {
var grid = super.createSlickGrid();
// need to register this plugin for grouping or you'll have errors
grid.registerPlugin(new Slick.Data.GroupItemMetadataProvider());
this.view.setSummaryOptions({
aggregators: [
new Slick.Aggregators.Sum('GrossAmount')
]
});
this.view.setGrouping(
[{
getter: 'ContactName'
}]);
return grid;
}
protected getSlickOptions() {
var opt = super.getSlickOptions();
opt.showFooterRow = true;
return opt;
}
protected usePager() {
return false;
}
protected getQuickFilters() {
var filters = super.getQuickFilters();
// we create a date-range quick filter, which is a composite
// filter with two date time editors
var orderDate = this.dateRangeQuickFilter('OrderDate', 'Order Date');
// need to override its handler, as default date-range filter will set Criteria parameter of list request.
// we need to set StartDate and EndDate custom parameters of our CustomerGrossSalesListRequest
orderDate.handler = args => {
// args.widget here is the start date editor. value of a date editor is a ISO date string
var start = args.widget.value;
// to find end date editor, need to search it by its css class among siblings
var end = args.widget.element.nextAll('.s-DateEditor')
.getWidget(Serenity.DateEditor).value;
(args.request as CustomerGrossSalesListRequest).StartDate = start;
(args.request as CustomerGrossSalesListRequest).EndDate = end;
// active option controls when a filter editor looks active, e.g. its label is blueish
args.active = !Q.isEmptyOrNull(start) || !Q.isEmptyOrNull(end);
};
filters.push(orderDate);
return filters;
}
}
}
create index.cshtml
@{ ViewBag.Title = "Stored Procedure Grid"; } @section ContentHeader { <h1>@ViewBag.Title<small></small></h1> } <div class="alert alert-info alert-dismissable"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <p>How to use a stored procedure as a data source.</p> <p style="text-align: right;"> <b>Source Files:</b> @Html.AppSourceFile("Index.cshtml"), @Html.AppSourceFile("CustomerGrossSalesGrid.ts") @Html.AppSourceFile("CustomerGrossSalesEndpoint.cs") @Html.AppSourceFile("CustomerGrossSalesRepository.cs") @Html.AppSourceFile("CustomerGrossSalesListRequest.cs") @Html.AppSourceFile("CustomerGrossSalesColumns.cs") </p> </div> <div id="GridDiv"></div> <script type="text/javascript"> jQuery(function () { new Serene.BasicSamples.CustomerGrossSalesGrid($('#GridDiv'), {}).init(); Q.initFullHeightGridPage($('#GridDiv')); }); </script>
Call stored procedure action method from common controller.
namespace Serene.BasicSamples.Pages
{
using System.Web.Mvc;
using Views = MVC.Views.BasicSamples.Grids;
public partial class BasicSamplesController : Controller
{
public ActionResult CancellableBulkAction()
{
return View(Views.CancellableBulkAction.Index);
}
public ActionResult ConditionalFormatting()
{
return View(Views.ConditionalFormatting.Index);
}
public ActionResult CustomLinksInGrid()
{
return View(Views.CustomLinksInGrid.Index);
}
public ActionResult DragDropInTreeGrid()
{
Repositories.DragDropSampleRepository.PopulateInitialItems();
return View(Views.DragDropInTreeGrid.Index);
}
public ActionResult EnablingRowSelection()
{
return View(Views.EnablingRowSelection.Index);
}
public ActionResult GridFilteredByCriteria()
{
return View(Views.GridFilteredByCriteria.Index);
}
public ActionResult GroupingAndSummariesInGrid()
{
return View(Views.GroupingAndSummariesInGrid.Index);
}
public ActionResult InitialValuesForQuickFilters()
{
return View(Views.InitialValuesForQuickFilters.Index);
}
public ActionResult InlineActionButtons()
{
return View(Views.InlineActionButtons.Index);
}
public ActionResult InlineImageInGrid()
{
return View(Views.InlineImageInGrid.Index);
}
public ActionResult ProductExcelImport()
{
return View(Views.ProductExcelImport.Index);
}
public ActionResult QuickFilterCustomization()
{
return View(Views.QuickFilterCustomization.Index);
}
public ActionResult RemovingAddButton()
{
return View(Views.RemovingAddButton.Index);
}
public ActionResult StoredProcedureGrid()
{
return View(Views.StoredProcedureGrid.Index);
}
public ActionResult TreeGrid()
{
return View(Views.TreeGrid.Index);
}
public ActionResult ViewWithoutID()
{
return View(Views.ViewWithoutID.Index);
}
public ActionResult VSGalleryQA()
{
return View(Views.VSGalleryQA.Index);
}
public ActionResult WrappedHeaders()
{
return View(Views.WrappedHeaders.Index);
}
}
}