I have an issue where in a class using automatic attributes Json.Net adds k__BackingField to attribute names.
I looked at various recommendation (ie adding [JsonObject]) and none of them works for me.
I found one recommended solution is to do:
((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;
(https://stackoverflow.com/a/36910449/460084)
However I don't know where or how to do this in .NET Core 2.1 ? does this goes in Startup.cs ? how ?
Also I am not even sure that will help, as my class does not have [Serializable] to begin with.
Any help ? Is there really no simple way to change the default for Json.Net to use attribute names as is without the k__BackingField in .NET Core 2.1
Add it to the Startup.cs in ConfigureServices method:
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(options => (options.SerializerSettings.ContractResolver as DefaultContractResolver).IgnoreSerializableAttribute = true);
// ...
}
Related
I realize DI (ctor based) in .NET CORE is quite straight forward but if it comes to nested injections I struggle.
This is quite simple:
public void ConfigureServices(IServiceCollection services)
{
services.AddRavenDbDocStore(x => x.AfterInitializeDocStore = RavenConfiguration.AfterInitializeDocStore());
services.AddRavenDbAsyncSession();
services.AddSingleton(new ExceptionHelper());
services.AddScoped<ICompoundService>(x => new CompoundService(x.GetService<IAsyncDocumentSession>(), x.GetService<ExceptionHelper>()));
But whenever I need to register a type within e.g a lamba of another registration, I have problems resolving dependencies:
services.AddMvc(setup =>
{
ILogger logger; // how would I get that?
setup.Filters.Add(new ApiExceptionFilter(logger));
}).AddFluentValidation();
Is there a good way to deal with that?
I certainly do not want to call this in ConfigureServices
var sp = services.BuildServiceProvider();
I read about this in Resolving instances with ASP.NET Core DI from within ConfigureServices
but I do not reall see an elegant option here...
Update:
After reading comments I realized that you can register Filters per type:
setup.Filters.Add<ApiExceptionFilter>()
Then you would not have to pass dependencies in the first place.
Still I wonder if there is a best practice for similar scenarios where you cannot access ServiceProvider in the lambda.
I have the following :
a class library with connection classes such as connection, command, parameter
a DAL with entities, mapper, interface, services as well as a static class that holds hard coded connectionString and InvariantName.
an Asp.Net Core project
References :
DAL has a reference to the class library to make use of its connection class to which it provides connectionString and InvariantName thanks to its static class etc..
Asp.Net has a reference to the DAL.
What I want :
I now want to use the User Secrets to store hard coded sensitive data connections and get rid off the static class.
I know I can use the the Asp.Net Core startup.cs to read the settings from Configuration and make use of binding to store them into a class and use DI.
My guess :
DI seems "easy" when used inside an Asp controller. But I need the settings values (connectionString and InvariantName) outside the Asp.Net Core to be injected into a constructor of a class somewhere in my DAL.
I guess I would then need to have to reference the Asp.Net Core project to my DAL. But then I would end up with a circular reference (DAL to Asp.Net Core and the opposite).
So what's the solution?
Have an intermediate library class into which I would retreive the settings values from Asp.Net Core and then pass them to my DAL (to prevent circular reference)?
Manually recreate the "Configuration process" inside the DAL and get settings there directly
Or something else that I don't know?
Ps : I am new in development and only have a few projects'experience in Asp.Net Framework so far..and it's my first Asp.Net Core project
I know I can use the the Asp.Net Core startup.cs to read the settings from Configuration and make use of binding to store them into a class and use DI
You already answered your own question with this. This is the correct and recommended behavior to setup DI for 3rd party libs and configurations. If you want to avoid clutter in Startup class, create an extension method:
namespace Microsoft.Extensions.DependencyInjetion
{
public static MyLibraryCollectionExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services)
{
services.AddDbContext<MyDbContext>(...);
}
}
}
to register your classes. Alternatively, extend the method to accept a parameter delegate to configure it
namespace Microsoft.Extensions.DependencyInjetion
{
public static MyLibraryCollectionExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services, Action<MyOptions> setup)
{
var defaultOptions = ... // i.e. new MyOptions();
// pass default options to be modified by the delegate
setup?.Invoke(defaultOptions);
// your registrations
services.AddDbContext<MyDbContext>(...);
}
}
}
And all the user has to do in your library is add
services.AddMyLibrary();
// or with setup
services.AddMyLibrary(config =>
{
config.MyConnectionString = Configuration.GetConnectionString("MyContext");
});
and store the connection string in the appsettings.json.
{
"ConnectionStrings":
{
"MyContext" : "MyConnectionString here"
}
}
I finally used the ConfigurationBuilder to get values from the appsettings.json file.
It's probably not the right way to do it but it is working with my DAL and Connection dlls.
In case it helps anyone else :
I am familiar with using ASP.NET Core with EF Core, where you just define your DBContext in the ConfigureServices method from Startup.cs for DI, like so:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
However, I have been asked to add Dapper to this project (it will still use EF) but I can't even fetch the connection string. I found Brad Patton's answer here to be along the lines of what I had in mind, but he leaves the setup of the Configuration object up to the reader:
public void ConfigureServices(IServiceCollection services)
{
...
// Add the whole configuration object here.
services.AddSingleton<IConfiguration>(Configuration);
}
After googling around for a couple of hours, I still have no idea of how to implement the IConfiguration interface. Any help is appreciated.
With ASP.NET Core 2.x you no longer need to register the IConfiguration type yourself. Instead, the framework will already register it with the dependency injection container for you. So you can just inject IConfiguration in your services directly.
You can also take a look at the options pattern to see how to implement the configuration for your own service layer. So you could do it like this:
services.Configure<MyDatabaseOptions>(options =>
{
options.ConnectionString = Configuration.GetConnectionString("DefaultConnection");
});
Assuming a MyDatabaseOptions type that you inject into your service using the options pattern.
I have Project 1 which is an ASP.NET Core application and Project 2 which is a .NET Standard library.
Is there a way to instantiate a DbContext found in Project 1 from my library using only the Type? I only want to get the metadata about it.
How does Scaffolding do it?
Example
var context = InstatiateFromType(typeof(MyContext));
// So that I get access to the metadata
var x = context.Model.FindEntityType(...);
I'm not sure I understood correctly.
But instead of instantiating it yourself, you could use get an instance via DI in your constructor.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<MyContext>(options => options.UseSqlServer("connectionString"));
}
And then in your Class you just get it via the constructor.
My current setup is using Ninject for simple IoC, everything goes fine, but I'm not able to resolve one of the classes I need inside my AuthorizeAttribute. I need to access a class that does ClaimsVerification:
Here's my code:
IoC Config:
var kernel = new StandardKernel(); // Ninject IoC
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<ISmartDocumentorUow>().To<SmartDocumentorUow>();
kernel.Bind<IClaimsVerification>().To<ClaimsVerification>();
// kernel
//kernel.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
MyAuthorizeAttribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
IClaimsVerification clamisverify { get; set; }
public MyAuthorizeAttribute()
{
//var x = System.Web.Mvc.DependencyResolver.Current.(typeof(IClaimsVerification));
}
Yap, sorry, the problem was injecting the iClaimsverification that isn't working in web api..
I tryed with the public property and still it didn't work.
the bindfilter is commented out, because it doesn't exist in the core NInject api (dll), it does exists in the MVC dll of ninject but it works for Action filters in the web mvc, and not in the api mvc for what i can tell..
i do solved the issue like this, though i don't like a lot of this fix:
private IClaimsVerification verifier
{
get
{
return (GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IClaimsVerification)) as IClaimsVerification);
}
}
The property you have marked with Inject is private - you need to initialize Ninject with a custom configuration to opt into what would be a much less efficient process
(You didnt state the problem in your question. I see you were trying BindFilter, but it's commented out (why?) - this is the correct approach. I recommend reading the Ninject.MVC3 wiki article on BindFilter for an example)