Rahul Rajput
Rahul Rajput

Reputation: 1437

Export to CSV file centrally in Asp.Net MVC

enter image description here

I am doing Export to csv functionality in my MVC project. Currently if i write code on each page it works properly. but i want to avoid duplication of code doing export functionality centrally.

Here is my controller code

public ActionResult Export(string filterBy)
        {
            GridState gs = new GridState();
            gs.Filter = filterBy;
            gs.Page = 1;
            gs.Size = int.MaxValue;
            IEnumerable cities = City.GetAll().AsEnumerable().AsQueryable().ToGridModel(gs).Data;
            MemoryStream output = new MemoryStream();
            StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
            writer.Write("Country Name,");
            writer.Write("State Name,");
            writer.Write("City Name,");
            writer.Write("City STD Code,");
            writer.Write("Is Display");
            writer.WriteLine();
            foreach (CityViewModel city in cities)
            {
                writer.Write(city.CountryName);
                writer.Write(",");
                writer.Write("\"");
                writer.Write(city.StateName);
                writer.Write("\"");
                writer.Write(",");
                writer.Write("\"");
                writer.Write(city.City.Name);
                writer.Write("\"");
                writer.Write(",");
                writer.Write(city.City.STDCode);
                writer.Write("\"");
                writer.Write(",");
                writer.Write(city.City.IsDisplay);
                writer.WriteLine();
            }
            writer.Flush();
            output.Position = 0;

            return File(output, "text/comma-separated-values", "city.csv");

        }

This is my View:

@model Telerik.Web.Mvc.GridModel<QuexstERP.BusinessCore.BusinessEntities.SysAdmin.CityViewModel>
@using Telerik.Web.Mvc.UI
@{
    ViewBag.Title = "City List";
}

@(Html.Telerik().Grid(Model.Data)
        .Name("Grid")
        .DataKeys(keys => keys.Add(c => c.City.Id))
            .ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { style = "margin-left:0", title = "Add" }))
                                .ToolBar(commands => commands
                .Custom()
                .HtmlAttributes(new { id = "TestFilter", onclick = "command_onClick(this)" })
                .Text("Export to csv")
                                        .Action("Export", "City", new { filterBy = "~" }))
            .DataBinding(dataBinding =>
                dataBinding.Server()
                    .Select("Select", "City", new { GridButtonType.Text })
                            .Insert("Create", "City", new { GridButtonType.Text })
                        .Update("Save", "City", new { GridButtonType.Text })
                        .Delete("Delete", "City", new { GridButtonType.Text }))
            .Columns(columns =>
            {
                columns.Command(commands =>
                {
                    commands.Custom("Edit").Action("Edit", "City").ImageHtmlAttributes(new { @class = "t-edit" }).ButtonType(GridButtonType.Image).HtmlAttributes(new { title = "Edit", @class = "RightAlign" });
                }).Width(40).Title("Edit").Visible(OperationHelper.EditOperation);

                columns.Command(commands =>
                {
                    commands.Delete().ButtonType(GridButtonType.Image).HtmlAttributes(new { title = "Delete", @class = "RightAlign" });
                }).Width(40).Title("Delete").Visible(OperationHelper.DeleteOperation);

                columns.Bound(p => p.CountryName).Width(200).Title("Country");
                columns.Bound(p => p.StateName).Width(200).Title("State");
                columns.Bound(p => p.City.Name).Width(310).Title("City");
                columns.Bound(p => p.City.STDCode).Width(200).Title("STD Code");
                columns.Bound(p => p.City.IsDisplay).Width(110).Title("IsDisplay");
            })
            .Pageable()
                .Scrollable()
            .Sortable()
                .Filterable()
                    .Resizable(command => command.Columns(true))
    )
@section HeadContent {

    <script type="text/javascript">
        function command_onClick(e) {

            var grid = $('#Grid').data('tGrid');

            var $cmd = $('#TestFilter');

            // Get its 'href' attribute - the URL where it would navigate to
            var href = $cmd.attr('href');

            // Update the 'filter' parameter with the grids' current filtering state
            href = href.replace(/filterBy=(.*)/, 'filterBy=' + (grid.filterBy || '~'));

            // Update the 'order' parameter with the grids' current ordering state
            href = href.replace(/orderBy=([^&]*)/, 'orderBy=' + (grid.orderBy || '~'));

            // Update the 'page' parameter with the grids' current page
            href = href.replace(/page=([^&]*)/, 'page=' + grid.currentPage);

            // Update the 'href' attribute
            $cmd.attr('href', href);
        }

    </script>
}

I want to do Export to CSV centrally. as many of the form like state, country and country in my project have the exporting functionality. is it possible to write one generic class and pass parameter to it. and export to csv is done centrally???

Upvotes: 0

Views: 2098

Answers (2)

Rahul Rajput
Rahul Rajput

Reputation: 1437

Just for the reference. Don't bind data to the grid and then export it to excel. It will give you

the file you are trying to open is in a different format than specified by the file extension

Error when you try to open Excel.

I have done this solution for above problem

public static void ExportToExcel(IEnumerable<dynamic> data, string sheetName)
{
    XLWorkbook wb = new XLWorkbook();
    var ws = wb.Worksheets.Add(sheetName);
    ws.Cell(2, 1).InsertTable(data);
    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    HttpContext.Current.Response.AddHeader("content-disposition", String.Format(@"attachment;filename={0}.xlsx",sheetName.Replace(" ","_")));

    using (MemoryStream memoryStream = new MemoryStream())
    {
        wb.SaveAs(memoryStream);
        memoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
        memoryStream.Close();
    }

    HttpContext.Current.Response.End();
}

It get data dynamically. use ClosedXml so no error and the Export to Excel functionality is central in application Hope this will help someone. :)

Upvotes: 0

Myles J
Myles J

Reputation: 2880

We achieved something similar to this by binding datasources to a GridView within a controller method e.g.

var data = GetSomeData();
var grid = new GridView { DataSource = data };
grid.DataBind();
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=MyExcel.xls");

Response.ContentType = "application/vnd.ms-excel";
var sw = new StringWriter();
var htw = new HtmlTextWriter(sw);

grid.RenderControl(htw);

Response.Write(sw.ToString());
Response.End();

This way you can just set the relevant datasource on the GridView and return a dump of the grid data in the output stream. With a bit of refactoring we were able to make this generic and it is now used by all of our UI grids for exporting to Excel/CSV.

Upvotes: 1

Related Questions