Mapster. How to get specific member configuration?
I need to find source member (and its value) by destination name. As a workaround i could create temporary model object but obviously this is undesirable approach 😅
Example using AutoMapper
// validation omitted for brevity
var map = this._mapper.ConfigurationProvider.FindTypeMapFor<TDto, TModel>();
var dtoPrimaryKey = modelPrimaryKey.Properties
.Select(x => map.GetPropertyMapByDestinationProperty(x.Name))
.Select(x => x.SourceMembers.First().GetMemberValue(dto))
.ToArray();
do you know?
how many words do you know
See also questions close to this topic
-
C# - Adding condition to func results in stack overflow exception
I have a func as part of specification class which sorts the given iqueryable
Func<IQueryable<T>, IOrderedQueryable<T>>? Sort { get; set; }
When i add more than one condition to the func like below , it results in stack overflow exception.
spec.OrderBy(sc => sc.Case.EndTime).OrderBy(sc => sc.Case.StartTime);
The OrderBy method is implemented like this
public ISpecification<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> property) { _ = Sort == null ? Sort = items => items.OrderBy(property) : Sort = items => Sort(items).ThenBy(property); return this; }
Chaining or using separate lines doesn't make a difference.
This problem gets resolved if I assign a new instance of the specification and set it's func, but i don't want to be assigning to a new instance everytime. Please suggest what am i missing here and how to reuse the same instance (if possible).
-
How to projection fields for a dictionary (C#, MongdoDB)
I am trying my luck here, I have a model which is like the following
public class RowData : BaseBsonDefinition { . [BsonExtraElements] [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] public Dictionary<string, object> Rows { get; set; } = new(StringComparer.OrdinalIgnoreCase); . }
In result, the schema in the MongoDB looks like
{ "_id": { "$binary": { "base64": "HiuI1sgyT0OZmcgGUit2dw==", "subType": "03" } }, "c1": "AAA", "c8": "Fully Vac", "c10": "", }
Those c1, c8 and c10 fields are keys from the dictionary, my question is how to dynamic project those fields?
I tried
Builders<RowData>.Projection.Exclude(p => "c1")
It seems the MongoDB driver can not handle a value directly.
Anyone could point me in the correct direction?
Thanks,
-
How do I add new DataSource to an already Databinded CheckBoxList
i'm building a web form that show Database's item(Tables, Rows, FK,...)
I have a CheckBoxList of Tables (
chkListTable
) which will show a new CheckBoxList of Rows (chkListRow
) everytime I SelectedIndexChanged fromchkListTable
. The problem is i can show the items fromchkListTable
with 1 selected item. But i don't know how to showchkListRow
if multiple item fromchkListTable
are selected.Here are my codes:
aspx
:<div> <asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label> <asp:CheckBoxList ID="chkListTable" runat="server" DataTextField="name" DataValueFeild="name" AutoPostBack="true" OnSelectedIndexChanged="chkListTable_SelectedIndexChanged"> </asp:CheckBoxList> </div> <div> <asp:CheckBoxList ID="chkListRow" runat="server" DataTextField="COLUMN_NAME" DataValueField="COLUMN_NAME" RepeatDirection="Horizontal"> </asp:CheckBoxList> </div>
aspx.cs
:protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e) { tableName.Clear(); foreach (ListItem item in chkListTable.Items) { if(item.Selected) { tableName.Add(item.Text.Trim()); } } for(int i = 0; i < tableName.Count; i++) { String query = "USE " + dbname + " SELECT * FROM information_schema.columns" + " WHERE table_name = '" + tableName[i] + "'" + " AND COLUMN_NAME != 'rowguid'"; chkListRow.DataSource = Program.ExecSqlDataReader(query); chkListRow.DataBind(); Program.conn.Close(); } }
Program.cs
:public static bool Connect() { if (Program.conn != null && Program.conn.State == ConnectionState.Open) Program.conn.Close(); try { Program.conn.ConnectionString = Program.constr; Program.conn.Open(); return true; } catch (Exception e) { return false; } } public static SqlDataReader ExecSqlDataReader(String query) { SqlDataReader myreader; SqlCommand sqlcmd = new SqlCommand(query, Program.conn); sqlcmd.CommandType = CommandType.Text; if (Program.conn.State == ConnectionState.Closed) Program.conn.Open(); try { myreader = sqlcmd.ExecuteReader(); return myreader; myreader.Close(); } catch (SqlException ex) { Program.conn.Close(); return null; } }
I want my display to be like this:
[x]Table1 [x]Table2 [ ]Table3 [ ]Row1(Table1) [ ]Row2(Table1) [ ]Row3(Table1) [ ]Row1(Table2) [ ]Row2(Table2)
-
Web API - Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2[Models.ServiceResult`1[Models.AuthResult]]
I am having a Project on ASP.NET Core-6 Web API using MapsterMapper, Fluent Validation and IMediatR
Interfaces:
public interface IRequestWrapper<T> : IRequest<ServiceResult<T>> { } public interface IRequestHandlerWrapper<in TRequest, TResponse> : IRequestHandler<TRequest, ServiceResult<TResponse>> where TRequest : IRequestWrapper<TResponse> { }
I did the response with ServiceResult as shown below.
ServiceResult:
public class ServiceResult<T> : ServiceResult { public T Data { get; set; } public ServiceResult(T data) { Data = data; } public ServiceResult(T data, ServiceError error) : base(error) { Data = data; } public ServiceResult(ServiceError error) : base(error) { } } public class ServiceResult { public bool Successful => this.Error == null; public ServiceError Error { get; set; } public ServiceResult(ServiceError error) { if (error == null) { error = ServiceError.DefaultError; } Error = error; } public ServiceResult() { } public static ServiceResult Failed(ServiceError error) { return new ServiceResult(error); } public static ServiceResult<T> Failed<T>(ServiceError error) { return new ServiceResult<T>(error); } public static ServiceResult<T> Failed<T>(T data, ServiceError error) { return new ServiceResult<T>(data, error); } public static ServiceResult<T> Success<T>(T data) { return new ServiceResult<T>(data); } }
ApplicationUserDto:
public class ApplicationUserDto : IRequest { public String Id { get; set; } public string Email { get; set; } public string UserName { get; set; } public string MobileNumber { get; set; } public bool? IsAdmin { get; set; } public DateTime LastLogin { get; set; } public void Register(TypeAdapterConfig config) { config.NewConfig<ApplicationUser, ApplicationUserDto>(); } }
AuthResult:
public class AuthResult { public string AccessToken { get; set; } public string TokenType { get; set; } public int ExpiresIn { get; set; } public string RefreshToken { get; set; } public ApplicationUserDto User { get; set; } public IList<string> Roles { get; set; } }
JwtTokenManager:
using MapsterMapper; public class JwtTokenManager : IJwtTokenManager { private readonly JwtSettings _jwtSettings; private readonly UserManager<ApplicationUser> _userManager; private readonly TokenValidationParameters _tokenValidationParameters; private readonly IMapper _mapper; public JwtTokenManager( JwtSettings jwtSettings, UserManager<ApplicationUser> userManager, TokenValidationParameters tokenValidationParameters, IMapper mapper ) { _jwtSettings = jwtSettings; _userManager = userManager; _tokenValidationParameters = tokenValidationParameters; _mapper = mapper; } public async Task<AuthResult> GenerateClaimsTokenAsync(string username, CancellationToken cancellationToken) { var user = await _userManager.FindByNameAsync(username); var roles = await _userManager.GetRolesAsync(user); var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // TODO: encrypt user id for added security new Claim(ClaimTypes.Name, username), new Claim(JwtRegisteredClaimNames.Sub, username), new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddMinutes(5)).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), }), Expires = DateTime.UtcNow.Add(_jwtSettings.Expiration), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var refreshTokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // TODO: encrypt user id for added security new Claim(ClaimTypes.Name, username), new Claim(JwtRegisteredClaimNames.Iss, _jwtSettings.Issuer), new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), }), Expires = DateTime.UtcNow.Add(_jwtSettings.Expiration), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; // Create JWT tokens var token = tokenHandler.CreateToken(tokenDescriptor); var refreshtoken = tokenHandler.CreateToken(refreshTokenDescriptor); return new AuthResult { AccessToken = tokenHandler.WriteToken(token), TokenType = "Bearer", ExpiresIn = _jwtSettings.Expiration.Seconds, RefreshToken = tokenHandler.WriteToken(refreshtoken), User = _mapper.Map<ApplicationUserDto>(user), Roles = roles }; } }
SignInCommand:
public class SignInCommand : IRequestWrapper<AuthResult> { public string Username { get; set; } public string Password { get; set; } }
the return AuthResult in JwtTokenManager is passed to SignInCommandHandler. Also SignInCommand is the request while AuthResult is the response.
SignInCommandHandler:
public class SignInCommandHandler : IRequestHandlerWrapper<SignInCommand, AuthResult> { private readonly ISignInManager _signInManager; private readonly IJwtTokenManager _jwtTokenManager; private readonly IIdentityService _identityService; public SignInCommandHandler(ISignInManager signInManager, IJwtTokenManager jwtTokenManager, IIdentityService identityService) { _signInManager = signInManager; _jwtTokenManager = jwtTokenManager; _identityService = identityService; } public async Task<ServiceResult<AuthResult>> Handle(SignInCommand request, CancellationToken cancellationToken) { // validate username & password var result = await _signInManager.PasswordSignInAsync(request.Username.ToLower().Trim(), request.Password.Trim(), false, false); // Throw exception if credential validation failed if (!result.Successful) { throw new UnauthorizedException("Invalid username or password."); } // Generate JWT token response if validation successful return ServiceResult.Success(await _jwtTokenManager.GenerateClaimsTokenAsync(request.Username, cancellationToken)); } }
Now the Controller:
public class AuthController : BaseApiController { private readonly IMediator _mediator; public AuthController(IMediator mediator) { _mediator = mediator; } [HttpPost] [Route(ApiRoutes.Auth.SignIn)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task<ActionResult<ServiceResult<AuthResult>>> SignIn(SignInRequest request, CancellationToken cancellationToken) { return Ok(await _mediator.Send(request, cancellationToken)); } }
DependencyInjection:
public static class DependencyInjection { public static IServiceCollection AddApplication(this IServiceCollection services) { // Register OAuth services services.AddTransient<IJwtTokenManager, JwtTokenManager>(); services.AddScoped<ISignInManager, SignInManager>(); services.AddTransient<IIdentityService, IdentityService>(); // Register Application Health Checks services.AddHealthChecks() .AddCheck<ApplicationHealthCheck>(name: "MY API"); // Register Fluent Validation service services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); // Register MediatR Services services.AddMediatR(Assembly.GetExecutingAssembly()); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>)); return services; } private static TypeAdapterConfig GetConfiguredMappingConfig() { var config = TypeAdapterConfig.GlobalSettings; IList<IRegister> registers = config.Scan(Assembly.GetExecutingAssembly()); config.Apply(registers); return config; } }
Program.cs:
var builder = WebApplication.CreateBuilder(args); // Add library project references for DependencyInjection builder.Services.AddApplication();
When I tried to Run the Application, I got this error:
System.AggregateException HResult=0x80131500 Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2[Auth.Commands.SignIn.SignInCommand,Models.ServiceResult`1[Models.AuthResult]] Lifetime: Transient ImplementationType: Auth.Commands.SignIn.SignInCommandHandler': Unable to resolve service for type 'MapsterMapper.IMapper' while attempting to activate 'Oauth.JwtTokenManager'.) (Error while validating the service descriptor 'ServiceType: Interfaces.IJwtTokenManager Lifetime: Transient ImplementationType: Oauth.JwtTokenManager': Unable to resolve service for type 'MapsterMapper.IMapper' while attempting to activate 'Oauth.JwtTokenManager'.) Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder) at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder) at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider() at Microsoft.Extensions.Hosting.HostBuilder.Build() at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() at Program.<Main>$(String[] args) in C:\Users\HP\Desktop\MyApp\WebApi\Program.cs:line 183 This exception was originally thrown at this call stack: [External Code] Inner Exception 1: InvalidOperationException: Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2[Auth.Commands.SignIn.SignInCommand,Models.ServiceResult`1[Models.AuthResult]] Lifetime: Transient ImplementationType: Auth.Commands.SignIn.SignInCommandHandler': Unable to resolve service for type 'MapsterMapper.IMapper' while attempting to activate 'Oauth.JwtTokenManager'. Inner Exception 2: InvalidOperationException: Unable to resolve service for type 'MapsterMapper.IMapper' while attempting to activate 'Oauth.JwtTokenManager'.
I already Mapped ApplicationUserDto
How do I resolve this
-
How to use Mapster to do type level mapping, with special mapping logic?
public static void Initialize() { TypeAdapterConfig<string?, DateTime?>.NewConfig() .MapWith(s => Convert(s)); } private static DateTime? Convert(string? s) => DateTime.TryParseExact( s, "dd/MM/yyyy", null, DateTimeStyles.None, out DateTime date) ? date : null;
Here's my workaround. If I didn't use the separate private method, the overloads of MapWith won't allow the
?
operator as the expression argument. Is there any other built-in way to achieve the same result?