Why to use Hashids?
Hashids helps you to convert a number Id to a string, this can make your app a little more secure hiding the actual id or related key of your DB when the data is requested by an API.
Why is useful ValueConverter of AutoMapper?
ValueConverter can handle the convertion inside te .Map<TDestination>(source)
method allowing you put the convertion logic in only one place.
The model
//Model of your data
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int ClassEnrollmentId { get; set; }
}
//Data Transfer Object (DTO) for your client
public class StudentDto
{
public string Id { get; set; }
public string Name { get; set; }
public string ClassEnrollmentId { get; set; }
}
The configuration
After you install the nuget packages:
Install-Package hashids.net
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
Add the following code to the Program.cs to use hashids and AutoMapper with dependency injection, if you prefer to use a class Startup you have to put it on the ConfigureServices method.
builder.Services.AddSingleton<IHashids>(_ =>
new Hashids("this is my salt"));
// Optional, you can set the length of the string
// new Hashids("this is my salt", [the number you want])
builder.Services.AddAutoMapper(typeof(AutoMapperProfile));
AutoMapperProfile
using AutoMapper; // To use the Profile class
public class AutoMapperProfile: Profile
{
public AutoMapperProfile()
{
//This configuration convert the int property who saves Ids to hash string
CreateMap<Student, StudentDto>()
.ForMember(d => d.Id, opt => opt.ConvertUsing<HashFormatter, int>())
.ForMember(d => d.ClassEnrollmentId, opt => opt.ConvertUsing<HashFormatter, int>());
//This configuration makes the oposite from the above configuration
CreateMap<StudentDto, Student>()
.ForMember(d => d.Id, opt => opt.ConvertUsing<IntFromHash, string>())
.ForMember(d => d.ClassEnrollmentId, opt => opt.ConvertUsing<IntFromHash, string>());
}
}
Convertion classes
using AutoMapper; //To use IValueConverter interface
using HashidsNet; //To use IHashids interface
public class HashFormatter : IValueConverter<int, string>
{
private readonly IHashids hashids;
public HashFormatter(IHashids hashids)
{
this.hashids = hashids;
}
public string Convert(int source, ResolutionContext context)
{
return hashids.Encode(source);
}
}
public class IntFromHash : IValueConverter<string, int>
{
private readonly IHashids hashids;
public IntFromHash(IHashids hashids)
{
this.hashids = hashids;
}
public int Convert(string source, ResolutionContext context)
{
return hashids.DecodeSingle(source);
}
}
How to use it
In a controller only have to inject AutoMapper and call the .Map
method like this.
public class StudentstController : ControllerBase
{
private readonly IMapper mapper;
public StudentstController(IMapper mapper)
{
this.mapper = mapper;
}
[HttpGet]
public IActionResult Get()
{
//Summaries is the data as List<Student>
return Ok(mapper.Map<List<StudentDto>>(Summaries));
}
}
Result
Data without hash
[
{
"id": 1,
"name": "Juan",
"classEnrollmentId": 2
},
{
"id": 2,
"name": "Pedro",
"classEnrollmentId": 1
}
]
Data with hash
[
{
"id": "NV",
"name": "Juan",
"classEnrollmentId": "6m"
},
{
"id": "6m",
"name": "Pedro",
"classEnrollmentId": "NV"
}
]
Thank you so much for reading this, I hope this be helpful.
Top comments (2)
Thank you so much for sharing!
Just a very small spelling. inject or inyect, AutoMapper not autommaper.
Thank you! It's corrected now.