3
\$\begingroup\$

I have a controller in an ASP.NET Web API application which generates a CSV file. The controller looks like this:

[System.Web.Http.HttpGet]
public HttpResponseMessage Download(int? id = null)
{
    if ( !id.HasValue)
        return new HttpResponseMessage(HttpStatusCode.NotFound);

    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new StreamContent(new MemoryStream(_personService
        .ExportPersonsToCSV().Content));
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
    result.Content.Headers.ContentDisposition = new 
        ContentDispositionHeaderValue("attachment") {  
            FileName = _personService.ExportPersonsToCSV().FileName };
    return result;
}

And method ExportPersonsToCSV() of PersonService class:

public FileDTO ExportPersonsToCSV()
{
    //...
    var dto = new FileDTO()
    {
        FileName = $"Persons {DateTime.Now}.csv",
        MediaTypeHeaderValue = Globals.MEDIA_TYPE_HEADER_VALUE,
        Content = _csvExport.WriteCSV(personDeps, columnNames)
    };
    return dto;
}

And CSVExport class looks like this:

public class CSVExport : ICSVExport
{
    /// <summary>
    /// Converting content of MemoryStream into byte array
    /// </summary>        
    public byte[] WriteCSV<T>(IEnumerable<T> objectlist
        , IEnumerable<string> columnNames = null)
    {
        byte[] bytes = null;
        using (var memStream = new MemoryStream())
        using (var sw = new StreamWriter(memStream, Encoding.GetEncoding("Windows-1251")))
        {
            sw.WriteLine("sep=,");
            foreach (var line in ToCsv(objectlist, columnNames))
            {
                sw.WriteLine(line);
            }
            sw.Flush();
            memStream.Seek(0, SeekOrigin.Begin);
            bytes = memStream.ToArray();
        }
        return bytes;
    }

    private IEnumerable<string> ToCsv<T>(IEnumerable<T> objectlist, 
         IEnumerable<string> columnNames = null, string separator = ",", 
         bool header = true)
    {
        //... code omitted for the brevity
        yield return string.Join(separator, fields                        
                    .ToArray());                
    }
}

Recently, I've thought whether a method public byte[] WriteCSV<T>(...) is a violation of Single Responsibility Principle?

My thought it is ok to place here:

  • It is appropriate place to put a logic of converting csv file into byte array cause a method public byte[] WriteCSV<T>(...) placed into a class CSVExport

My thoughts it is NOT ok to place here:

  • What is MemoryStream class doing here? It is a class of ExportCSV and nothing more!
  • It is possible to extract dependency(MemoryStream) into separate class like and use it into CSVExport: IMemoryStream{ byte[] WriteCSV(IEnumerable objects);}

So is a method public byte[] WriteCSV<T>(...) placed into CSVExport a violation of Single Responsibility Principle? Any other criticism are welcome.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Just curious, did you consider using a csv library such as CsvHelper ? \$\endgroup\$
    – Brad M
    Apr 2, 2019 at 20:34
  • \$\begingroup\$ @BradM Thanks for advice, however, I would like to implement by myself:) \$\endgroup\$
    – StepUp
    Apr 3, 2019 at 7:12

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.