Ignore and DoNotValidate not working for AutoMapper 8.1 and .NET Core 2.1 - .net-core

I have developed an azure function in .net core and configured automapper in startup.cs by builder.Services.AddAutoMapper(Assembly.GetAssembly(this.GetType()));
I am trying to create a map between domain class (table in EF core) and a DTO. The domain class has a property RowVersion . I want this property to be ignored while mapping dto to domain.
For this I created a Profile Class and created my custom map but this is not working.
I tried DoNotValidate , but it doesn't seem to work
Startup.cs
builder.Services.AddAutoMapper(Assembly.GetAssembly(this.GetType()));
public class MapperProfile :Profile
{
public MapperProfile()
{
CreateMap<MyDto, MyDomain>().ForMember(i => i.RowVersion, opt => opt.Ignore());
}
}
Service.cs
_mapper.Map<myDomain>(myDtoInstance)
getting the below error
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
Unmapped properties:
[5/28/2019 7:00:40 AM] RowVersion

ForMember is used for referencing the destination objects, in your case, MyDto.
Use ForSourceMember instead:
public MapperProfile()
{
CreateMap<MyDto, MyDomain>().ForSourceMember(i => i.RowVersion, opt => opt.Ignore());
}

Related

Scoped service in DBContext with DBContextFactory can't resolve from root provider

I want to register a scoped ICurrentUserService and then use it in the DbContext to set the CreatedBy property on every entity. I want it scoped because it uses the current HttpContext to get the user id from the claims and the HttpContext is scoped by definition.
services.AddTransient<ICurrentUserService, CurrentUserService>();
However when I try to use this with the DbContextFactory like this:
services.AddDbContextFactory<MyDbContext>(options =>
options.UseSqlServer(config.ConnectionStrings.MSSQLConnection, x =>
{
x.MigrationsHistoryTable("...");
x.MigrationsAssembly("...");
}));
services.AddScoped<IMyDbContext>(provider => provider.GetRequiredService<IDbContextFactory<MyDbContext>>().CreateDbContext());
services.AddScoped<MyDbContext>(provider => provider.GetRequiredService<IDbContextFactory<MyDbContext>>().CreateDbContext());
I get the error
Cannot resolve scoped service 'SomeNamespace.ICurrentUserService' from root provider.
I can change it to Transient but that seems wrong and will probably be an issue later on for testing when I want to mock this and every class gets a new instance.
I'm actually not sure why Scoped does not work here. The DbContextFactory is registered Singleton but the Context is resolved as Scoped too.
Try it with ServiceLifetime.Scoped
services.AddDbContextFactory<ApplicationDbContext>(contextOptions =>
... YOUR OPTIONS
), ServiceLifetime.Scoped);

Swagger API definition load API definition - Cant use schema id "$Module"

I am getting this exception when I want to create a Domain object with name Module
InvalidOperationException: Can't use schemaId "$Module" for type "$Pro.Core.Domain.Module". The same schemaId is already used for type "$System.Reflection.Module"
Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.RegisterType(Type type, string schemaId)
Seems like this name Module is conflicting with some System.Reflection.Module.
I have searched the internet and I have below 2 solutions that can get this working:
Rename my Module class name to something else but not Module(lets say MyModule)
Doing something like below
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(config =>
{
//some swagger configuration code.
//use fully qualified object names
config.CustomSchemaIds(x => x.FullName);
}
}
But I want to understand that what is there in name Module that creates this error. I don't see any reason for not being allowed to use this name as my domain class name.
Is there any way to use the Domain Object with name Module other that mentioned above in point 2 and why is this happening in the first place?
Fixed by using
services.AddSwaggerGen(options =>
{
options.CustomSchemaIds(type => type.ToString());
});
Find more details from
here

How to release or distribute an application that uses mikro-orm?

In the configuration I have to specify the paths to .js and .ts files defining entities:
MikroORM.init({
...
entitiesDirs: ["build/entities"],
entitiesDirsTs: ["src/entities"],
});
So, when I will go to release or distribute the application. Will I need distribute the typescript code too? or will I need distribute only the cache generated? or will I need distribute both? or... none?
As of MikroORM v2.2
Now you can work with default metadata provider, it will require entity source files only if you do not provide entity or type options in your decorators (you can use entity callback to use reference to entity class instead of using string name in type, handle for refactoring via IDE like webstorm).
Original answer:
You should ship the typescript code too, and let the cache regenerate on the server - cache would be rebuilt anyway as it checks absolute path to cached entity for invalidation.
You could implement your own cache adapter or metadata provider to get around this, if you don't want to ship the typescript code.
This is how you could implement custom metadata provider that simply throws error when the type option is missing:
import { MetadataProvider, Utils } from 'mikro-orm';
import { EntityMetadata } from 'mikro-orm/dist/decorators';
export class SimpleMetadataProvider extends MetadataProvider {
async loadEntityMetadata(meta: EntityMetadata, name: string): Promise<void> {
// init types and column names
Object.values(meta.properties).forEach(prop => {
if (prop.entity) {
prop.type = Utils.className(prop.entity());
} else if (!prop.type) {
throw new Error(`type is missing for ${meta.name}.${prop.name}`)
}
});
}
}
Then provide this class when initializing:
const orm = await MikroORM.init({
// ...
metadataProvider: SimpleMetadataProvider,
});
The value of type should be JS types, like string/number/Date... You can observe your cached metadata to be sure what values should be there.
Also keep in mind that without TS metadata provider, you will need to specify entity type in #ManyToOne decorator too (either via entity callback, or as a string via type).

Is it possible to configure everything within context?

I am trying to configure Audit.net and define my custom logic for saving logs.
Is there a way to configure included entities within context?
I tried this
`
public ResidentMasterContext(DbContextOptions options) : base(options)
{
AuditDataProvider = new DynamicDataProvider();
Mode = AuditOptionMode.OptIn;
IncludeEntityObjects = true;
EntitySettings = new Dictionary<Type, EfEntitySettings>
{
{typeof(Apartment), new EfEntitySettings()}
};
}
`
but OnScopeSaving is not firing. And when I change mode to OptOut it takes all entities
I guess you are referring to the Audit.NET EntityFramework extension.
if you use OptIn you need to mark the included entities with [AuditInclude] attribute, or use the Include methods of the fluent API. You can check the documentation here.
An example using the fluent API for the EF configuration, to include only the entities User and UserDetail:
Audit.EntityFramework.Configuration.Setup()
.ForContext<ResidentMasterContext>(config => config
.IncludeEntityObjects())
.UseOptIn()
.Include<User>()
.Include<UserDetail>();
An example of the output configuration:
Audit.Core.Configuration.Setup()
.UseDynamicProvider(_ => _.OnInsertAndReplace(auditEvent =>
{
Console.WriteLine(auditEvent.ToJson());
}));

Using StructureMap 3 in multiple ASP MVC projects

First lets start to describe my project architecture.
I have a asp.net mvc application called Portal.Web as startup project and multiple asp.net mvc applications which called Plugin.XXX (Plugin.News, Plugin.Cms, etc) and Portal.Web has references from all of these plugins.
I installed StrcutureMap.Mvc5 for each one of these Plugins
As you know, when you install StructureMap a folder created called DependencyResolution and it contains some files, one of them is IoC.cs where you can initialize your container.
Now my problem is since all plugins has their own IoC.cs, it seems like they override each other containers so at the end I get this error :
No parameterless constructor defined for this object
// inner exception
No default Instance is registered and cannot be automatically determined for type 'Portal.Plugins.Page.Interfaces.IPage'
There is no configuration specified for Portal.Plugins.Page.Interfaces.IPage
1.) new RouteController(*Default of IUnitOfWork*, *Default of IPage*)
2.) Portal.Web.Controllers.RouteController
3.) Instance of Portal.Web.Controllers.RouteController
4.) Container.GetInstance(Portal.Web.Controllers.RouteController)
There is no configuration specified for Portal.Plugins.Page.Interfaces.IPage
I could use ONE IoC.cs in Portal.Web project but I need to keep modularity and make Plugins independent as much as possible.
is there any way to keep plugins containers independent?
namespace Portal.Plugins.Account.DependencyResolution {
using StructureMap;
public static class IoC {
public static IContainer Initialize() {
return new Container(c =>
{
c.AddRegistry<DefaultRegistry>();
c.For<IUnitOfWork>().LifecycleIs(new HttpContextLifecycle()).Use<AccountDbContext>();
c.For<IAccount>().Use<AccountService>();
});
}
}
}
namespace Portal.Plugins.Cms.DependencyResolution {
using StructureMap;
public static class IoC {
public static IContainer Initialize() {
return new Container(c =>
{
c.AddRegistry<DefaultRegistry>();
c.For<IUnitOfWork>().LifecycleIs(new HttpContextLifecycle()).Use<CmsDbContext>();
c.For<IPage>().Use<PageService>();
c.For<IMenu>().Use<MenuService>();
c.For<IMedia>().Use<MediaService>();
});
}
}
}
If I understand your problem correctly, couldn't you create a DependencyResolution class library that contains the StructureMap.Mvc5 package that's then used throughout your plugins (this saves each of your plugins containing versions of StructureMap.Mvc5) and having a single reference to your DependencyResolution class library.
From here your individual plugins can then contain their own StructureMap registries, with more global registries being kept in the DependencyResolution class library.

Resources