IChangeSetItemAuthorizer in RESTier 1.0 - restier

Can anyone point me to an example project using IChangeSetItemAuthorizer for custom authorization in RESTier 1.0.

Couple months after the fact, but I just came across this issue yesterday. You need to change the access modifier from protected to public.
So in their example it would change from this:
protected static new IServiceCollection ConfigureApi(Type apiType, IServiceCollection services)
{
return EntityFrameworkApi<TrippinModel>.ConfigureApi(apiType, services)
.AddService<IChangeSetItemAuthorizer, CustomizedAuthorizer>();
}
To this:
public static new IServiceCollection ConfigureApi(Type apiType, IServiceCollection services)
{
return EntityFrameworkApi<TrippinModel>.ConfigureApi(apiType, services)
.AddService<IChangeSetItemAuthorizer, CustomizedAuthorizer>();
}

Related

.NET CORE 2.1 Constructor asks for IConfiguration

I've followed several methods on StackOverflow to fix my issue, none with a result:
My DefaultConnection-string is in my AppSettings.json. To retrieve info I am reading to use the IConfiguration from my startup.cs. The constructor of my MsSQL-context is still asking for this IConfiguration. Note: I'm using a repository pattern.
startup.cs:
public Startup(IConfiguration configuration)
{
this.Configuration = configuration;
}
public IConfiguration Configuration { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
I've added the Singleton in my startup after a suggestion. With or without this the constructor of MsSQLContext is still requesting this as a variable to be passed. Leaving the constructor without this gives me the error: Connectionstring not initialized.
AdminMsSQLContext:
private readonly string _connectionString;
public MSSQLAdminContext(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("DefaultConnection");
}
Injecting IConfiguration is actually an anti-pattern, anyways. What you should be doing is supplying an action to your scope registration and change your MSSQLAdminContext class to accept just the connection string in its constructor:
public MSSQLAdminContext(string connectionString)
{
_connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
}
Then:
services.AddScoped(_ =>
new MSSQLAdminContext(Configuration.GetConnectionString("DefaultConnection)));
Your repo should not have knowledge of something like your configuration. If it needs a connection string, then it should take the connection string, and that is all.
I believe the issue you are having is that you have not registered the MSSQLAdminContext with the DI container. Because of this the DI engine does not know to inject the IConfiguration into the class. In your start up you will register this class however you need, I tend to use scoped for these types of classes you may use in multiple places. So something like this.
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<MSSQLAdminContext>();
services.AddSingleton<IConfiguration>(Configuration);
}

How to inject SignalR Hub Class (not hubcontext) into Controller

public class ComputerHub : Hub
{
private readonly DbContext _db;
public ComputerHub(DbContext db)
{
_db = db;
}
public Task OpenLock(string connectionId)
{
return Clients.Client(connectionId).SendAsync("OpenLock");
}
...
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
....
app.UseSignalR(routes =>
{
routes.MapHub<ComputerHub>("/computerhub");
});
....
}
I want to reach the OpenLock method in a controller. How should I add to ServiceCollection the computerhub in the startup.cs.
You don't seem to understand how this works. To simply answer your question, to inject the class directly, it simply needs to be registered with the service collection, like any other dependency:
services.AddScoped<ComputerHub>();
However, that's not going to do what you want it to. The class itself doesn't do anything. It's the hub context that bestows it with its powers. If you simply inject an instance of the class, without the hub context, then things like Clients (which the method you want to utilize uses) won't be set and won't have any of the functionality they need to actually do anything useful.

.net core resolve dependency manually anywhere in the code

Do you know how to manually resolve dependencies in .net core?
Something like
DependencyResolver.Resolve<ISomeService>()
UPDATE
I'm in a class that was not injected, I want to resolve it from the inside, rather than pass variables all over the place
Add your dependency in ConfigureServices as below
public void ConfigureServices(IServiceCollection services){
//AddSingleton or AddTransient based on your requirements
services.AddTransient<ISomeService, ConcreteService>();
}
In your controller or anywhere, add IServiceProvider in the constructor like below:
using Microsoft.Extensions.DependencyInjection;
...
public class HomeController
{
...
public HomeController(IServiceProvider serviceProvider)
{
var service = serviceProvider.GetService<ISomeService>();
}
}
#Shazam, Here are some notes or suggestions based on your comment:
If you can not inject because you might not have a constructor in this class, I woud suggest to add a paramter to your function and pass the resolved dependency from outside
Another Idea is to add a static property and initialize its value in ConfigureServices
For Example:
public static class MyClass
{
public static ISomeService MyServiceObj { set; get; }
....
}
In your ConfigureServices
public void ConfigureServices(IServiceCollection services){
services.AddTransient<ISomeService, ConcreteService>();
MyClass.MyServiceObj = services.GetService<ISomeService>();
}
Hope this helps, please rate my answer or leave me a comment if you still in doubt how to do it

asp.net core web api, how to inject the connection string

Here is my asp.net core project structure
1- ASP.NET CORE Web API (contains aspsettings.json)
"ConnectionStrings": {
"DefaultConnection": "Server=(local)\\SQLEXPRESS;Database=testdb;Trusted_Connection=True;"
}
2-SERVICES Project (Web API Call method from Services Project)
3-REPOSITORY Project (Services call method from Repository Project and Repository Project include the DATA Project where all the models are)
4-DATA Project where it's contain all the model with code first
public class TtEntities : DbContext
{
public virtual DbSet<RoomMessage> RoomMessage { get; set; }
public virtual DbSet<UserRoom> UserRoom { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Server=(local)\SQLEXPRESS;Database=testdb;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
As you can see, I hardcoded the connection on the method OnConfiguring which is not the best practice for sure.
Is there a way to pass the connection string from the configuration file of the Web API Project?
Is update database command will still work if we pass the connection from the file aspsettings.json from web api project ?
Thanks a lot
A simple solution is like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
}
Consider how DefaultConnection is used in line 13. Also a sample appsettings is like as follow:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplication5;"
}
}
DI solves this problem perfectly and .NET Core 2.0 has Microsoft DI thats provides clearly experience with DI.
oh, lets starts(i think that DATA Project and REPOSITORY Project should be one)
from REPOSITORY Project
change your REPOSITORYClass to
public class REPOSITORYClass
{
private readonly TtEntities _db;
public REPOSITORYClass (TtEntities db){
_db = db;
}
//some your staff of REPOSITORYClass thats uses _db
}
now go to SERVICES Project
lets change some service that uses REPOSITORYClass
public class SomeService
{
private readonly REPOSITORYClass _repo;
public SomeService (REPOSITORYClass repo){
_repo = repo;
}
//other staff of SomeService thats uses _repo
}
after that go to ASP.NET CORE Web API startup file and add to
public void ConfigureServices
// Get connection of your repo
string connection = Configuration.GetConnectionString("DefaultConnection");
// add TtEntities as service
services.AddDbContext<TtEntities>(options =>
options.UseSqlServer(connection));
//add your repo
services.AddTransient<REPOSITORYClass>();
//add your service
services.AddTransient<SomeService>();
now go to the contoller thats uses your SomeService
public class SomeController: Controller
{
private readonly SomeService _someService;
public SomeController(SomeService someService){
_someService = someService;
}
//And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
public string SomeMethod()
{
return _someService.SomeMethod();
}
}
And use whatever your wants from your service that injected with deps of repo and injected db entity with connection
thats all
PS also recommend to read this Introduction to Dependency Injection in ASP.NET Core

Access IConfiguration in the ActionFilterAttribute in the asp.net core rc2 application [duplicate]

This question already has answers here:
Inject service into Action Filter
(6 answers)
Closed 6 years ago.
I am writing attribute that will verify captcha. In order to work correctly it needs to know secret, which I keep in the settings (Secret manager tool). However I don't know how to read config from the attribute class. DI in asp.net core supports constructor injection (and property injection is not supported), so this will give compilation error:
public ValidateReCaptchaAttribute(IConfiguration configuration)
{
if (configuration == null)
{
throw new ArgumentNullException("configuration");
}
this.m_configuration = configuration;
}
because when I decorate method with [ValidateReCaptcha] I can't pass config
So how do I can read something from config from the method in attribute class?
You can use ServiceFilter attribute, more info in this blog post and asp.net docs.
[ServiceFilter(typeof(ValidateReCaptchaAttribute))]
public IActionResult SomeAction()
In Startup
public void ConfigureServices(IServiceCollection services)
{
// Add functionality to inject IOptions<T>
services.AddOptions();
// Add our Config object so it can be injected
services.Configure<CaptchaSettings>(Configuration.GetSection("CaptchaSettings"));
services.AddScoped<ValidateReCaptchaAttribute>();
...
}
And ValidateReCaptchaAttribute
public class ValidateReCaptchaAttribute : ActionFilterAttribute
{
private readonly CaptchaSettings _settings;
public ValidateReCaptchaAttribute(IOptions<CaptchaSettings> options)
{
_settings = options.Value;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
...
base.OnActionExecuting(context);
}
}
You should use ServiceFilter like this:
[ServiceFilter(typeof(ValidateReCaptcha))]
And if you want to use IConfiguration you should inject it in ConfigureServices:
services.AddSingleton((provider)=>
{
return Configuration;
});

Resources