2

Here's what I'm using: AngularJS, BreezeJS on the client side. For the server, I'm using Web API and MVC 5.

I've been searching for ways on how to build and retrieve an excel spreadsheet from the server, but I'm at a loss.

I found this plugin called linqtocsv that helps greatly in building the csv file out of linq. The codeproject example is found here and the nuget link is found here.

I also found nice useage on a question on stackover flow: Web API HttpResponseMessage content return is incomplete

So after implementing the above plugin - linq to csv, and following the mentioned stackover question, nothing seems to be working.

Here is my server side code (both taken directly from the link mentioned already):

    [HttpPost]
    public HttpResponseMessage DistributorReport(JObject formValues)
    {
        try
        {
            var cqmo = formValues.ToObject<DistributorCQMO>();

            var query = new FindDistributorsByLocationQuery
            {
                States = cqmo.States.Select(x => x.id),
                Cities = cqmo.Cities.Select(x => x.id),
                CitiesExclusion = cqmo.ExcludedCities.Select(x => x.id),
                ZipCodes = cqmo.ZipCodes.Select(x => x.id),
                ZipCodesExclusion = cqmo.ExcludedZipCodes.Select(x => x.id),
                ProductFamily = cqmo.ProductFamily.id,
                ProductSubFamilies = cqmo.ProductSubFamily.Select(x => x.id),
                MatchAllFilter = cqmo.MatchAllFilter,
                ClientTypeFilter = cqmo.ClientTypeFilter
            };



            IEnumerable<DistributorDTO> distributors = this.queryProcessor.Process(query).AsQueryable();

            CsvFileDescription outputFileDescription = new CsvFileDescription
            {
                SeparatorChar = '\t', // tab delimited
                FirstLineHasColumnNames = true
            };


            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new CsvContent<DistributorDTO>(outputFileDescription,
                                                           "ObserverTripList.csv",
                                                            distributors)
            };

            return response;

        }  
        catch (Exception ex)  
        {  
            // logger.ErrorException("Exception exporting as excel file: ", ex);  
            return Request.CreateResponse(HttpStatusCode.InternalServerError);  
        } 
    }

and here's the helper class:

public class CsvContent<T> : HttpContent
{
    private readonly MemoryStream _stream = new MemoryStream();
    public CsvContent(CsvFileDescription outputFileDescription, string filename, IEnumerable<T> data)
    {
        var cc = new CsvContext();
        var writer = new StreamWriter(_stream);
        cc.Write(data, writer, outputFileDescription);
        writer.Flush();
        _stream.Position = 0;

        Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        Headers.ContentDisposition.FileName = filename;

    }
    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        return _stream.CopyToAsync(stream);
    }

    protected override bool TryComputeLength(out long length)
    {
        length = _stream.Length;
        return true;
    }
}

I tried using breeze to make my post, which returns the data wrapped up in the breeze object, and if after digging into the returned object, into it's httpreponse property, you'll see in its raw form, the tabbed delimited data, however, the content application is in application/json; charset=utf-8 and not of excel formatting.

EDIT:

I have the following now working:

    $.ajax({
        type: 'POST',
        url: 'MappingTool.API/api/Report/DistributorReport',
        data: JSON.stringify(jsonData),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        success: function (returnValue) {
            alert("success")
           // window.location = '/Reports/Download?file=' + returnValue;
            }
    });

I'm getting the correct response and able to view all the results in fiddler and in chrome debugger. But how do I get the browser to download the file automatically?

any feedback is appreciated!

Edit:

Is this something that I should be fetching from an MVC controller or an API controller? It seems there is more support for an MVC controller, like the FileResult type that can be used in MVC; which would give me my automatic download: "exporting excel file to view mvc" I've seen it being done using an API controller; but isn't the point of an API controller to delegate simple data types, and not media content?

Community
  • 1
  • 1
sksallaj
  • 3,872
  • 3
  • 37
  • 58
  • Can you post your Web API controller that is handling the POST request? Also have you tried just making the request manually in fiddler to ensure it is not an issue with your client-side code? – Ben Foster Mar 10 '14 at 22:36
  • editted it. The thing is, I think my web api controllers are sending off the data by default as json. It only works when I use breezejs's post, maybe I'm doing something incorrectly when I use jquery ajax. I'm looking for different alternatives. But this is getting a bit frustrating. – sksallaj Mar 10 '14 at 23:12
  • 2
    As per my previous comment you should try hitting your API with Fiddler. This way you can identify exactly where the issue is. You could inspect the HTTP request/response in Chrome's dev tools (network tab). – Ben Foster Mar 10 '14 at 23:16
  • ah right, it IS returning content-type: application/octet-stream. Now I'm getting somewhere! I just modified my ajax.. and I'm getting a 200 response back with the correct format; now how do I get the browser to automatically detect the type of the data I'm getting back? – sksallaj Mar 10 '14 at 23:43
  • Did you try setting dataType: "text/csv"? – victormejia Apr 08 '14 at 18:55
  • use `File()` http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.file(v=vs.118).aspx – Mardoxx Sep 10 '14 at 14:44

0 Answers0