YourITGroup / MemberListView

Back-Office Member Management for Umbraco 7 & 8
27 stars 18 forks source link

Export members with special characters #4

Closed bjarnef closed 6 years ago

bjarnef commented 7 years ago

When exporting members with special characters in name, e.g. danish letters like æ, ø and å, it doesn't use correct encoding.

For example: æ -> æ ø -> ø å -> Ã¥

bjarnef commented 7 years ago

Okay, when opening the csv in Excel it looked correct using Encoding.GetEncoding(1252) .. howeverwhen importing via CMSImport or just viewing the csv with this tool the characters were incorrect http://www.convertcsv.com/csv-viewer-editor.htm

In an ApiController I have the following.

[HttpGet]
public HttpResponseMessage Export()
{
    var ms = Services.MemberService;
    var allMembers = ms.GetAllMembers();

    //Build the CSV file data as a Comma separated string.
    StringBuilder sb = new StringBuilder();

    //Add the Header row for CSV file.
    sb.AppendLine("Id,Guid,Login,Email,Name,IsApproved,IsLockedOut,MemberType,MemberGroups,CreateDate,LastLoginDate,LastLockoutDate,LastPasswordChangeDate,Password");

    foreach (var member in allMembers)
    {
        var rolesList = Roles.GetRolesForUser(member.Username);

        //Add the Data rows.
        sb.Append(member.Id + ",");
        sb.Append(member.Key + ",");
        sb.Append("\"" + member.Username + "\"" + ",");
        sb.Append("\"" + member.Email + "\"" + ",");
        sb.Append("\"" + member.Name + "\"" + ",");
        sb.Append(member.IsApproved + ",");
        sb.Append(member.IsLockedOut + ",");
        sb.Append("\"" + member.ContentTypeAlias + "\"" + ",");
        sb.Append("\"" + string.Join(",", rolesList) + "\"" + ",");

        sb.Append(member.CreateDate + ",");
        sb.Append(member.LastLoginDate + ",");
        sb.Append(member.LastLockoutDate + ",");
        sb.Append(member.LastPasswordChangeDate + ",");

        sb.Append("\"" + member.RawPasswordValue + "\"" + ",");

        //sb.Append(member.Comments + ",");

        //Add new line.
        sb.AppendLine();
    }

    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new StringContent(sb.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); //Encoding.GetEncoding(1252));
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    result.Content.Headers.ContentDisposition.FileName = string.Format("Members_{0:yyyyMMdd}.csv", DateTime.Now);

    return result;
}
robertjf commented 7 years ago

Hi @bjarnef

I've added support for Unicode to the Export as you've suggested - I also added a sample website project (using a SqlCe database) - see the ReadMe for more details.

If you want to test this out for me I'd appreciate it; I haven't yet released a nuget package with the updates but will do so over the next day or so.

bjarnef commented 7 years ago

I noticed you get member groups using MemberService

// Resolve groups into a comma-delimited string.
// Resolve groups into a comma-delimited string.
var roles = ApplicationContext.Current.Services.MemberService.GetAllRoles(member.Id);
if (roles != null)
{
    member.Groups = roles.Aggregate("", (a, b) => (a == "" ? a : a + ",") + b);
}

I did it a bit different, but not sure which is best.

var rolesList = Roles.GetRolesForUser(member.Username);
string.Join(",", rolesList)
robertjf commented 7 years ago

Given that we've got the Umbraco context, I believe the MemberService would be the preferred way of doing it; it accesses the database directly by default (https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs#L176-L189). Roles.GetRoles() would probably work just as well, and the underlying Umbraco MembershipProvider probably just uses the MemberService anyway (I haven't checked)