Search code examples
c#asp.netasp.net-mvcentity-frameworkcsvhelper

How i can change the order of the fields and the fields names inside my CSVHelper


I am working on an asp.net mvc 4 web application + entity framework 5.0, and i have the following method which call a function named AdvanceSearchStoredProcedure, where this function will call a stored procedure:-

     public IQueryable<AdvanceSearchSP_Result> AdvanceSearch(NetworkAdvanceSearch na)
      {

        var r = entities.AdvanceSearchStoredProcedure("network",na.AssetTypeID,
        na.ip, na.ipselection, na.mac, na.macselection);
        return r.AsQueryable();           

      }

then i am calling this method from my action method as follow:-

public ActionResult AdvanceSearchIndexExport(AdvanceSearchSP_Result2 ns)

        {
            var result = WriteCsvToMemory(repository.AdvanceSearch(ns.NetwotkAS).ToList());
            var memoryStream = new MemoryStream(result);
            return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
        }
public byte[] WriteCsvToMemory(IEnumerable<AdvanceSearchSP_Result> records)
      {
          using (var memoryStream = new MemoryStream())
          using (var streamWriter = new StreamWriter(memoryStream))
          using (var csvWriter = new CsvWriter(streamWriter))
          {
              csvWriter.WriteRecords(records);
              streamWriter.Flush();
              return memoryStream.ToArray();
          }
      }

here is a partial class for my AdvanceSearchSP_Result and its MetadataType class:-

[MetadataType(typeof(AdvanceSearchSP_Result_Validation))]

    public partial class AdvanceSearchSP_Result
    {


    }
public class AdvanceSearchSP_Result_Validation{
        [Display(Name="Service Tag")]
        public string SERVICETAG { get; set; }
         [Display(Name = "Serial Number")]
        public string SERIALNO { get; set; }
        [Display(Name = "Resource Tag")]
         public string Tag { get; set; }
        [Display(Name = "Resource Name")]
         public string RESOURCENAME { get; set; }
        [Display(Name = "State")]
         public string StateName { get; set; }
        [Display(Name = "Type")]
         public string TypeName { get; set; }
        [Display(Name = "Site Name")]
         public string sitename { get; set; }
        [Display(Name = "Customer Name")]
         public string cusotmername { get; set; }
         public bool ismanaged { get; set; }
}

now i am facing these problems inside the generated .CSV file:-

  1. the fields title will be equal to the column names inside the database, and not as defined inside the AdvanceSearchSP_Result_Validation MetadataType class.

  2. second question, i am not sure how i can change the order of the columns? as currently the order will be as the one defined inside the stored procedure..for example how i can force the ismanaged to be the first column inside the .csv file??

i am using the CSVHelper https://www.nuget.org/packages/CsvHelper/ library to do the actual CSV export.

EDIT now i added this class:-

public sealed class SPMap : ClassMap<AdvanceSearchSP_Result>
    {
        public SPMap()
    {
        Map(m => m.Tag).Name("Resource Tag").Index(0);
        Map(m => m.RESOURCENAME).Name("Asset Name").Index(1);
        Map(m => m.cusotmername).Name("Customer Name").Index(2);
        Map(m => m.sitename).Name("Site Name").Index(3);
        Map(m => m.StateName).Name("Asset State").Index(4);
        Map(m => m.ismanaged).Name("ismanaged").Index(5);
        Map(m => m.TypeName).Name("Technology Type ").Index(6);
        Map(m => m.SERVICETAG).Name("Service Tag").Index(7);
        Map(m => m.SERIALNO).Name("Serial Number").Index(8);

    }
    }

then i modify my method to include the configuration as follow:-

 public byte[] WriteCsvToMemory(IEnumerable<AdvanceSearchSP_Result> records)
      {
          using (var memoryStream = new MemoryStream())
          using (var streamWriter = new StreamWriter(memoryStream))
          using (var csvWriter = new CsvWriter(streamWriter))
          {
              csvWriter.WriteRecords(records);
              csvWriter.Configuration.RegisterClassMap<SPMap>();
              streamWriter.Flush();
              return memoryStream.ToArray();
          }
      }

but still i got the old names & the old order.. so seems the public sealed class SPMap : ClassMap<AdvanceSearchSP_Result> did not have any effect...


Solution

  • I think you need a map to specify the names and indices of the columns:

    public sealed class SPMap : ClassMap<AdvanceSearchSP_Result>
    {
        public SPMap()
        {
            Map(m => m.SERVICETAG).Name("Service Tag").Index(0);
            Map(m => m.sitename).Name("Site Name").Index(1);
            /*repeat for other properties */
            ..
            .. 
        }
    }
    

    Then you need to register this:

    csvWriter.Configuration.RegisterClassMap<SPMap>();
    

    I believe that'll work.

    See : http://joshclose.github.io/CsvHelper/mapping