[CLOSED] [1.0] MVC Grid/Store Export to .xls/.csv/.xml Error

Page 1 of 4 123 ... LastLast
  1. #1

    [CLOSED] [1.0] MVC Grid/Store Export to .xls/.csv/.xml Error

    Hello,

    I am having an issue with being able to export store results to excel. This is the same problem raised in the following thread: http://forums.ext.net/showthread.php...tom+TextWriter

    However, the solution wasn't listed. I think the end solution would have been to write a custom ActionResult which handles the "post" action and correctly creates the export as per the routines listed in the examples explorer. This would be required because of changes to the ASP.NET MVC View Engine between version 1 and 2.

    Are you able to provide a solution that includes a custom ActionResult that can be used in a controller as opposed to page behind code?

    I have a solution that reproduces the problem which I have attached to this post. It is a cut down version of my projects code.
    Attached Files
  2. #2
    Hi,

    You have to set IsUpload for DirectEvent and use FileContentResult
    Please see
    http://forums.ext.net/showthread.php...ownload-in-MVC
    http://forums.ext.net/showthread.php...light=download
  3. #3
    Hi Vlad, thanks for the reply.

    This, I don't think is the issue though. I have IsUpload set to true and I get the same behaviour whether on a form or not. I can also carry out file downloads okay (edit: file downloads using action results in other scenarios i should point out).

    The problem is the parsing of the data. Normally, when the export of grid data is carried out you have a function like:

    
    switch (format)
                {
                    case "xml":
                        string strXml = e.Xml.OuterXml;
                        Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xml", "Test"));
                        Response.AddHeader("Content-Length", strXml.Length.ToString());
                        Response.ContentType = "application/xml";
                        Response.Write(strXml);
                        break;
    
                    case "xls":
                        Response.ContentType = "application/vnd.ms-excel";
                        Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", "Test"));
                        XslCompiledTransform xtExcel = new XslCompiledTransform();
                        xtExcel.Load(HttpContext.Current.Server.MapPath("~/Content/Excel.xsl"));
                        xtExcel.Transform(e.Xml, null, Response.OutputStream);
                        break;
    
                    case "csv":
                        Response.ContentType = "application/octet-stream";
                        Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.csv", "Test"));
                        XslCompiledTransform xtCsv = new XslCompiledTransform();
                        xtCsv.Load(HttpContext.Current.Server.MapPath("~/Content/Csv.xsl"));
                        xtCsv.Transform(e.Xml, null, Response.OutputStream);
                        break;
                }
    This works fine with code behind in WinForms and MVC 1 however, in MVC 2 it will not work because the MVC View Engine makes assumptions about the resultant OutputStream. For example see: http://efreedom.com/Question/1-22611...lAnswersMarker

    "When a ViewPage begins executing, it assumes certain things about the remainder of the request. The particular thing that is tripping you up is that a ViewPage assumes that the remainder of the request will be a normal HTML or some other textual response, so it switches the response's TextWriter with its own writer."

    Therefore, I have had to write a custom ActionResult like the following:

    
    public class ExportResult : ActionResult
        {
            private readonly string format;
    
            public ExportResult(string format)
            {
                this.format = format;
            }
    
            public override void ExecuteResult(ControllerContext context)
            {
                var response = context.RequestContext.HttpContext.Response;
                var request = context.RequestContext.HttpContext.Request;
    
                XmlNode submitConfig = JsonConvert.DeserializeXmlNode(request.Params["submitDirectEventConfig"]);
    
                string data = string.Empty;
    
                XmlNode serviceNode = submitConfig.SelectSingleNode("config/serviceParams");
    
                if (serviceNode != null)
                {
                    data = serviceNode.InnerText;
                }
    
                data = HttpUtility.HtmlDecode(data);
    
                XmlNode node = JsonConvert.DeserializeXmlNode("{records:{record:" + data + "}}");
    
                response.Clear();
    
                switch (format)
                {
                    case "xml":
                        string strXml = node.OuterXml;
                        response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xml", "Test"));
                        response.AddHeader("Content-Length", strXml.Length.ToString());
                        response.ContentType = "application/xml";
                        response.Write(strXml);
                        break;
    
                    case "xls":
                        response.ContentType = "application/vnd.ms-excel";
                        response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", "Test"));
                        XslCompiledTransform xtExcel = new XslCompiledTransform();
                        xtExcel.Load(HttpContext.Current.Server.MapPath("~/Content/Excel.xsl"));
                        xtExcel.Transform(node, null, response.OutputStream);
                        break;
    
                    case "csv":
                        response.ContentType = "application/octet-stream";
                        response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.csv", "Test"));
                        XslCompiledTransform xtCsv = new XslCompiledTransform();
                        xtCsv.Load(HttpContext.Current.Server.MapPath("~/Content/Csv.xsl"));
                        xtCsv.Transform(node, null, response.OutputStream);
                        break;
                }
    
                response.Flush();
            }
        }
    However, this is not ideal for two reasons, I have had to take a load of the Ext code which turns the submitDirectEventConfig parameters into an XmlNode, whereas with the code behind Url this is done for you. I may have to stick with this, but wondered if there was a better way?
  4. #4
    Hi,

    Why you don't want to use FileContentResult? You can transform to string (XslCompiledTransform) and pass it to FileContentResult
    http://discuss.joelonsoftware.com/de...et.12.310872.6
    http://geekswithblogs.net/slock/arch...21/109398.aspx
  5. #5
    Yes, I could do that, or I can use what I have finally come up with above.

    I guess then this should more of be a question as to whether it is OK to extract the XML in the way that I have been doing at the Controller stage because at this point the Ext code hasn't been invoked to do it for me?
  6. #6
    Hi,

    whether it is OK to extract the XML in the way that I have been doing at the Controller stage because at this point the Ext code hasn't been invoked to do it for me?
    I am not sure that properly understood you. What 'Ext code' do you mean?
  7. #7
    In my ExportResult class, I have the following code in the ExecuteResult function:

    
    XmlNode submitConfig = JsonConvert.DeserializeXmlNode(request.Params["submitDirectEventConfig"]);
     
                string data = string.Empty;
     
                XmlNode serviceNode = submitConfig.SelectSingleNode("config/serviceParams");
     
                if (serviceNode != null)
                {
                    data = serviceNode.InnerText;
                }
     
                data = HttpUtility.HtmlDecode(data);
     
                XmlNode node = JsonConvert.DeserializeXmlNode("{records:{record:" + data + "}}");
    Which I have taken from the Ext.NET source code. It is used to fetch the records submitted as part of submitDirectEventConfig from the request parameter collection and then transform it into an XmlNode. When you use the code behind method demonstrated in the Ext.NET examples, this code is run behind the scenes as part of the Ext.NET engine prior to the Store Submit event handler running.

    So, is this the correct way to go about getting hold of an XmlNode of records (which I can then transform using the methods already discussed), or, is there another (either more MVC or generally 'correct') way which is recommend by yourselves?

    Edit: Also, given the page structure that I have setup in my example attached to my first post. Is it possible to make the store submit to a different URL? I have tried changing the DirectEventConfig but this doesn't seem to work. I have tried to wrap my Grid/Store in a standard <form> tag with an action attribute but this breaks my layout because I can't use a FitLayout.
  8. #8
    Hi,

    Correct way is mannualy submit data to the controller action
    <Click url="Controller/Action">
          <ExtraParams>
                 <ext:Parameter Name="data" Value="GridPanel1.getRowsValues()" Mode="Raw" Encode="true"/>
          </ExtraParams>
    </Click>
    
    public ActionResult Action(string data)
    {
        Ext.Net.SubmitHandler submitData = new Ext.Net.SubmitHandler(data);
        string json = submitData.Json;
        XmlNode xml = submitData.Xml;
        List<MyBusinessEntity> objects = submitData.Object<MyBusinessEntity>();
    
        //proceessin data...
    
       return new FileContentResult( ... );
    }
  9. #9
    Hi Vlad,

    Thanks for the alternate way of doing it. I have set up my handlers as below:

    
    <DirectEvents>
        <Click Url="/Home/Write" IsUpload="true">
            <ExtraParams>
                <ext:Parameter Name="data" Value="#{gpPremises}.getRowsValues()" Mode="Raw" Encode="true" />
                <ext:Parameter Name="format" Value="xls" Mode="Value" />
            </ExtraParams>
        </Click>
    </DirectEvents>
    However, this returns with a popup window saying: 'BADRESPONSE: null as no properties' as the status text and a message of "PREMIDADDR1ADDR2ADDR3ADDR4POSTCODE-1abcde-2abcde-3abcde-4abcde" which is the contents of my export.

    I was going to try it as a non direct event (<Listeners>) but there is no Url parameter on Click. I suspect my event handler is wrong in some way?
  10. #10
    Hi,

    Can you provide your action code. Which result class do you use?
Page 1 of 4 123 ... LastLast

Similar Threads

  1. [CLOSED] how to export few columns from grid store to excel?
    By rnachman in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Mar 28, 2012, 8:32 PM
  2. [CLOSED] MVC Grid/Store Export to .xls/.csv/.xml
    By softmachine2011 in forum 1.x Legacy Premium Help
    Replies: 9
    Last Post: Jun 17, 2011, 1:16 PM
  3. [CLOSED] Export dynamically created Grid/Store
    By CarWise in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: May 05, 2011, 12:40 PM
  4. Replies: 1
    Last Post: Apr 19, 2010, 2:44 PM
  5. [CLOSED] Error 500 saving grid store
    By harafeh in forum 1.x Legacy Premium Help
    Replies: 4
    Last Post: Jun 30, 2009, 2:59 PM

Posting Permissions