I'm getting a 400 Error when I click on the toolbar button to export the grid contents to Excel. The call to the ProxyURL method never happens.
Chrome Dev Tools shows the following.
POST https://localhost:44329/Admin/Companies?handler=Read 400
I suspect this is because the Anti-Forgery token is not getting passed to the read that the export function uses although it looks like the same read call that the grid uses successfully. Any ideas on how I can resolve this?
@(Html.Kendo().Grid<
InstallerCompanyPageModel
>()
.AutoBind(false)
.Name("CompaniesGrid")
.Columns(columns =>
{
columns.Command(command => { command.Edit()
.HtmlAttributes(new { title = "Edit", @class = "k-button k-button-icontext" })
.UpdateText("Save"); }).Width(100);
columns.Bound(a => a.CompanyName).Width(200)
.Filterable(filterable => filterable.Extra(false)
.Operators(operators => operators
.ForString(str => str.Clear()
.StartsWith("Starts with")
.Contains("Contains")
))
);
columns.Bound(a => a.WebSite).Width(250)
.HtmlAttributes(new { @class = "wordWrapGridColumn" })
.Filterable(filterable => filterable.Extra(false)
.Operators(operators => operators
.ForString(str => str.Clear()
.StartsWith("Starts with")
.Contains("Contains")
))
);
columns.Bound(a => a.Active).Width(60)
.ClientTemplate("#= Active ? 'Yes' : 'No' #").HtmlAttributes(new { style = "text-align:center" });
})
.ToolBar(toolbar => toolbar.Custom().Text("<
i
class
=
'fas fa-file'
></
i
> Add New")
.HtmlAttributes(new { id = "companyAdd", title = "Add a new company.", @class = "k-button k-button-icontext k-grid-add" }))
.ToolBar(toolbar => toolbar.Custom().Text("<
i
class
=
'fas fa-sync'
></
i
> Refresh Grid")
.HtmlAttributes(new { id = "companyRefresh", title = "Refresh the data in the grid." }))
.ToolBar(toolbar => toolbar.Custom().Text("<
i
class
=
'fas fa-minus-square'
></
i
> Clear Filters")
.HtmlAttributes(new { id = "companyReset", title = "Clear the grid column filters." }))
.ToolBar(toolbar => toolbar.Custom().Text("<
i
class
=
'fas fa-file-excel'
></
i
> Export To Excel")
.HtmlAttributes(new { id = "export", title = "Export to Excel", @class = "k-button k-button-icontext k-grid-excel" }))
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable(pageable => pageable
.Input(true)
.Numeric(false)
.PageSizes(true)
.Messages(messages => messages.Display("Showing items from {0:0,0} to {1:0,0}. Total items: {2:0,0}"))
.Messages(messages => messages.Empty("No companies found."))
.PageSizes(new[] { 5, 10, 25, 50 })
)
.Resizable(resizeable => resizeable.Columns(true))
.Sortable()
.Scrollable(s => s.Height("auto"))
.Filterable()
.Excel(excel => excel
.AllPages(true)
.Filterable(true)
.FileName("Companies.xlsx")
.ProxyURL(Url.Action("Excel_Export_Save", "Grid"))
)
.Events(events => events.ExcelExport("excelExport1"))
.DataSource(dataSource => dataSource
.Ajax()
.Read(r => r.Url("/Admin/Companies?handler=Read"))
.Update(u => u.Url("/Admin/Companies?handler=Update"))
.Create(c => c.Url("/Admin/Companies?handler=Create"))
.Model(m =>
{
m.Id(id => id.InstallerCompanyId);
m.Field(i => i.CompanyName);
m.Field(i => i.WebSite);
m.Field(i => i.Active).DefaultValue(true);
})
.PageSize(10)
.Sort(sortable => sortable.Add("CompanyName"))
.Events(events => events.Error("gridErrorHandler"))
)
)
My JavaScript
$(
function
() {
// razor pages have built in anti-forgery token so wire up the kendo grid to pass it when doing crud
var
grid = $(
"#CompaniesGrid"
).data(
"kendoGrid"
);
grid.dataSource.transport.options.read.beforeSend =
function
(req) {
req.setRequestHeader(
'RequestVerificationToken'
, $(
'input:hidden[name="__RequestVerificationToken"]'
).val());
};
grid.dataSource.transport.options.update.beforeSend =
function
(req) {
req.setRequestHeader(
'RequestVerificationToken'
, $(
'input:hidden[name="__RequestVerificationToken"]'
).val());
};
grid.dataSource.transport.options.create.beforeSend =
function
(req) {
req.setRequestHeader(
'RequestVerificationToken'
, $(
'input:hidden[name="__RequestVerificationToken"]'
).val());
};
});
My controller method
[HttpPost]
public
ActionResult Excel_Export_Save(
string
contentType,
string
base64,
string
fileName)
{
var fileContents = Convert.FromBase64String(base64);
return
File(fileContents, contentType, fileName);
}