How to get IOptions in ConfigureServices method or pass IOptions into extension method? - asp.net-web-api

I'm developing asp .net core web api 2.1 app.
I add JWT authentication service as an extension method in static class:
public static class AuthenticationMiddleware
{
public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, string issuer, string key)
{
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
// validate the server that created that token
ValidateIssuer = true,
// ensure that the recipient of the token is authorized to receive it
ValidateAudience = true,
// check that the token is not expired and that the signing key of the issuer is valid
ValidateLifetime = true,
// verify that the key used to sign the incoming token is part of a list of trusted keys
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
ValidAudience = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
});
return services;
}
}
which I use in ConfigureServices method of Startup class like this:
public void ConfigureServices(IServiceCollection services)
{
// adding some services omitted here
services.AddJwtAuthentication(Configuration["Jwt:Issuer"], Configuration["Jwt:Key"]);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Now, I have a requirement to use IOptions pattern to get JWT authentication data from appsettings.json
How can I get IOptions in ConfigureServices method to pass issuer and key into extension method? Or how to pass IOptions to extension method?

For binding data from appsettings.json to Model, you could follow steps below:
Appsettings.json content
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"JWT": {
"Issuer": "I",
"Key": "K"
}
}
JWT Options
public class JwtOptions
{
public string Issuer { get; set; }
public string Key { get; set; }
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<JwtOptions>(Configuration.GetSection("JWT"));
var serviceProvider = services.BuildServiceProvider();
var opt = serviceProvider.GetRequiredService<IOptions<JwtOptions>>().Value;
services.AddJwtAuthentication(opt.Issuer, opt.Key);
services.AddMvc();
}
One more option to pass JwtOptions directly.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<JwtOptions>(Configuration.GetSection("JWT"));
var serviceProvider = services.BuildServiceProvider();
var opt = serviceProvider.GetRequiredService<IOptions<JwtOptions>>().Value;
services.AddJwtAuthentication(opt);
services.AddMvc();
}
Change the extension method.
public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, JwtOptions opt)

One other option is to bind the configurations to a class with the Bind() extension. (IMO this a more clean solution then the IOptions)
public class JwtKeys
{
public string Issuer { get; set; }
public string Key { get; set; }
}
public void ConfigureServices(IServiceCollection services)
{
var jwtKeys = new JwtKeys();
Configuration.GetSection("JWT").Bind(JwtKeys);
services.AddJwtAuthentication(jwtKeys);
}
public static IServiceCollection AddJwtAuthentication(this IServiceCollection services, JwtKeys jwtKeys)
{....}
Then if you need the JwtKeys settings some other place in the solution, just register the class on the collection and inject it where needed
services.AddSingleton(jwtKeys);

You can add your options to DI container in Startup class like this:
public class JwtOptions
{
public string Issuer { get; set; }
public string Key { get; set; }
}
public void ConfigureService(IServiceCollection services)
{
services.AddOptions();
services.Configure<JwtOptions>(Configuration.GetSection("Jwt"));
}
Now you can use this options, in a configure stage, or in an extension method:
public void Configure(IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IOptions<JwtOptions>();
// write your own code
}

Related

Options are not passed to the class

I'm trying to pass options to the class via the constructor from the appsettings.json file.
The file itself looks like this:
"IDP": {
"UrlCbr": "https://www.cbr-xml-daily.ru/daily_json.js",
"UrlDadata": "https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/currency",
"DadataToken": "94dabe1e8342c21fdad9622be29514d4f0f99bbd8",
"BotToken": "1549046386:AAHJsdsaMVaCT-8O3D_P8VLxw6EKAr4P9JfSU",
"BotName": "Hop_hipBot",
"BotUrl": "https://111295d46c69.ngrok.io/{0}"
}
To do this, I created the IDP.cs class:
public class IDP
{
public string UrlCbr { get; set; }
public string UrlDadata { get; set; }
public string DadataToken { get; set; }
public string BotToken { get; set; }
public string BotName { get; set; }
public string BotUrl { get; set; }
}
Then in the Startup.cs I'm making a connection:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddNewtonsoftJson();
services.Configure<IDP>(Configuration.GetSection("IDP"));
}
I need this data in the implementation of the bot:
class Bot
{
private static TelegramBotClient botClient;
private static IOptions<IDP> _IDPs;
public void Temp(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
public static async Task<TelegramBotClient> GetBotClientAsync()
{
if (botClient != null)
{
return botClient;
}
botClient = new TelegramBotClient(_IDPs.Value.BotToken);
var hook = string.Format(_IDPs.Value.BotUrl, #"api/bot");
await botClient.SetWebhookAsync(hook);
return botClient;
}
}
Well, the bot itself is launched in Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Bot.GetBotClientAsync().Wait();
}
And when you run the entire application, the _IDPs field in the bot turns out to be null. Why is this happening and how do I need to properly deliver the data to the bot? In other classes, everything works correctly and options are passed
You have a bug in the Bot class. Change:
public void Temp(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
To :
public class Bot
{
.....
private static IOptions<IDP> _IDPs;
public Bot(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
......
}
Change your code like below:
public class Bot
{
private static IOptions<IDP> _IDPs;
public static void Temp(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
public static async Task GetBotClientAsync()
{
var data = _IDPs.Value.BotToken;
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
//more services...
services.Configure<IDP>(Configuration.GetSection("IDP"));
var serviceProvider = services.BuildServiceProvider();
Bot.Temp(serviceProvider.GetService<IOptions<IDP>>());
Bot.GetBotClientAsync().Wait();
}
Result:

Access appsettings.json in class library

I search for a solution to access the appsettings.json within a class library. I have a ASP.NET Core web application which depends on a class library. In this class library I must read some properties from the appsettings.json.
Are there any way to do that?
You should probably use Options
It's fairly simple to use. Check this article. it's well explained Src
1/ Create your Options class
namespace UsingOptions.Models
{
public class MyOptions
{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}
public string Option1 { get; set; }
public int Option2 { get; set; } = 5;
}
}
2/ Configure it in the ConfigureServices method (In startup.cs)
public void ConfigureServices(IServiceCollection services)
{
// Adds services required for using options.
services.AddOptions();
// Register the IConfiguration instance which MyOptions binds against.
**services.Configure<MyOptions>(Configuration);**
// Add framework services.
services.AddMvc();
}
3/ Inject IOptions into your controller
public class HomeController : Controller
{
private readonly MyOptions _options;
public HomeController(IOptions<MyOptions> optionsAccessor)
{
_options = optionsAccessor.Value;
}
public IActionResult Index()
{
var option1 = _options.Option1;
var option2 = _options.Option2;
return Content($"option1 = {option1}, option2 = {option2}");
}
}

ASP.NET Core—access Configuration from static class

I want a simple static class that accesses the Configuration object. All the config info is already read in from the appsettings.json file in the Startup class. I just need an easy way to access it. Is this possible?
namespace MyNamespace
{
public static class Config
{
public string Username => Configuration["Username"];
public string Password => Configuration["Password"];
}
}
Anywhere else in the app:
string username = Config.Username;
string password = Config.Password;
A slightly shorter version based on the same principle as above...
public Startup(IConfiguration configuration)
{
Configuration = configuration;
StaticConfig = configuration;
}
public static IConfiguration StaticConfig { get; private set; }
To use in another static class:
string connString = Startup.StaticConfig.GetConnectionString("DefaultConnection");
create the ConfigurationHelper static class in the service layer, so it can be used in other layers without circular dependency.
public static class ConfigurationHelper
{
public static IConfiguration config;
public static void Initialize(IConfiguration Configuration)
{
config = Configuration;
}
}
initialize the ConfigurationHelper inside the ConfigureServices method in the Startup class.
ConfigurationHelper.Initialize(Configuration);
Use it wherever you want including your static classes
e.g: ConfigurationHelper.config.GetSection("AWS:Accesskey").Value;
After much research, this works (in ASPNetCore 2.2) for accessing the appsettings.json config from a static class but for some reason appsettings.development.json no longer loads properly but it might be something else in my project messing that up. The reloadOnChange does work. As a bonus it also has IHostingEnvironment and IHttpContextAccessor. While this works, I have recently decided to switch back to a more DI approach to follow the paradigm shift as others have mentioned.
So here is one of many ways to access some DI stuff (including the configuration) in a static class:
AppServicesHelper.cs:
public static class AppServicesHelper
{
static IServiceProvider services = null;
/// <summary>
/// Provides static access to the framework's services provider
/// </summary>
public static IServiceProvider Services
{
get { return services; }
set
{
if (services != null)
{
throw new Exception("Can't set once a value has already been set.");
}
services = value;
}
}
/// <summary>
/// Provides static access to the current HttpContext
/// </summary>
public static HttpContext HttpContext_Current
{
get
{
IHttpContextAccessor httpContextAccessor = services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
return httpContextAccessor?.HttpContext;
}
}
public static IHostingEnvironment HostingEnvironment
{
get
{
return services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment;
}
}
/// <summary>
/// Configuration settings from appsetting.json.
/// </summary>
public static MyAppSettings Config
{
get
{
//This works to get file changes.
var s = services.GetService(typeof(IOptionsMonitor<MyAppSettings>)) as IOptionsMonitor<MyAppSettings>;
MyAppSettings config = s.CurrentValue;
return config;
}
}
}
}
Startup.cs:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddHttpContextAccessor();//For HttpContext.
// Register the IOptions object
services.Configure<MyAppSettings>(Configuration.GetSection(nameof(MyAppSettings)));
//Explicitly register the settings object by delegating to the IOptions object so that it can be accessed globally via AppServicesHelper.
services.AddSingleton(resolver => resolver.GetRequiredService<IOptionsMonitor<MyAppSettings>>().CurrentValue);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
AppServicesHelper.Services = app.ApplicationServices;
//...
}
Controller:
public class MyController: Controller
{
public MyController()
{
}
public MyAppSettings Config => AppServicesHelper.Config;
public async Task<IActionResult> doSomething()
{
testModel tm = await myService.GetModel(Config.Setting_1);
return View(tm);
}
}
Another class library:
public static class MyLibraryClass
{
public static string GetMySetting_ => AppServicesHelper.Config.Setting_1;
public static bool IsDev => AppServicesHelper.HostingEnvironment.IsDevelopment();
}
MyAppSettings.cs is any class that maps to a MyAppSettings section in appsettings.json:
public class MyAppSettings
{
public string Setting_1 {get;set;}
}
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"MyAppSettings": {
"Setting_1": "something"
}
}
I've similar problems, and after reading the document from Microsoft. I've resolved it:
Create an static ApplicationSettings class
public static class ApplicationSettings
{
public const string User = "UserOptions";
public static UserOptions UserOptions { get; set; } = new UserOptions();
// other options here...
}
Create an options class
public class UserOptions
{
public string Username { get; set; };
public string Password { get; set; };
}
Init the Options class in Program.cs
ConfigurationManager configuration = builder.Configuration;
configuration.GetSection(ApplicationSettings.User).Bind(ApplicationSettings.UserOptions);
Update your appsettings.json
{
"UserOptions": {
"Username": "input_your_username_here",
"Password": "input_your_password_here"
}
}
You can call it anywhere in your project now
public void MethodA()
{
string username = ApplicationSettings.UserOptions.Username;
string password = ApplicationSettings.UserOptions.Password;
}
public static void MethodB()
{
string username = ApplicationSettings.UserOptions.Username;
string password = ApplicationSettings.UserOptions.Password;
}
Hope this could help you well.
I agree with mcbowes, it's in the docs, but the first example looks more like what you need...want:
public class Program
{
public static IConfigurationRoot Configuration { get; set; }
public static void Main(string[] args = null)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
Console.WriteLine($"option1 = {Configuration["option1"]}");
// Edit:
IServiceCollection services = new ServiceCollection();
services.AddOptions();
services.Configure<HelloWorldOptions>(_configuration.GetSection("HelloWorld"));
// And so on...
}
}
Try avoid using a static class and use DI
namespace MyNamespace {
public interface IConfig {
string Username { get; }
string Password { get; }
}
public class Config : IConfig {
public Config(IConfiguration configuration) {
_configuration = configuration;
}
readonly IConfiguration _configuration;
public string Username => _configuration["Username"];
public string Password => _configuration["Password"];
}
}
The setup DI in StartUp class
public class Startup {
public void ConfigureServices(IServiceCollection services) {
//...
services.AddTransient<IConfig, Config>();
...
}
}
And use it like so
public class TestUsage {
public TestUsage(IConfig config) {
_config = config;
}
readonly IConfig _config;
public string Username => _config.Username;
public string Password => _config.Password;
}
You can use Signleton pattern to access your configurations from anywhere
public class ConnectionStrings
{
private ConnectionStrings()
{
}
// property with getter only will not work.
public static ConnectionStrings Instance { get; protected set; } = new ConnectionStrings();
public string DatabaseConnection { get; set; }
}
and in your startup class
public class Startup
{
private readonly IConfiguration configuration;
public Startup(IConfiguration configuration)
{
this.configuration = configuration;
configuration.GetSection("ConnectionStrings").Bind(ConnectionStrings.Instance);
}
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app)
{
}
}
This has already been said but I'm going to say it.
I believe .Net Core wants developers to get values through Dependency Inject. This is what I've noticed from my research but I am also speculating a bit. As developers, we need to follow this paradigm shift in order to use .Net Core well.
The Options Pattern is a good alternative to the static config. In your case, it'll look like this:
appsettings.json
{
"Username": "MyUsername",
"Password": "Password1234"
}
SystemUser.cs
public class SystemUser
{
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
Startup.cs
services.Configure<SystemUser>(Configuration);
And to use the SystemUser class, we do the following.
TestController.cs
public class TestController : Controller
{
private readonly SystemUser systemUser;
public TestController(IOptionsMonitor<SystemUser> systemUserOptions)
{
this.systemUser = systemUserOptions.CurrentValue;
}
public void SomeMethod()
{
var username = this.systemUser.Username; // "MyUsername"
var password = this.systemUser.Password; // "Password1234"
}
}
Even though we are not using a static class, I think this is the best alternative that fits your needs. Otherwise, you might have to use a static property inside the Startup class which is a scary solution imo.
Personally I like the method used in this link
Essentially it just adding a static field to your options class.
public class WeblogConfiguration
{
public static WeblogConfiguration Current;
public WeblogConfiguration()
{
Current = this;
}
}
Then in any static class you can do:
WeblogConfiguration.Current
Simple and very straight forward
If you are using environment variables as your configuration, you can access the environment variable directly rather than via the configuration object.
using System;
namespace My.Example
{
public static class GetPaths
{
private static readonly string MyPATH =
Environment.GetEnvironmentVariable("PATH");
private static readonly string MySpecialPath =
Environment.GetEnvironmentVariable("PREFIX_SpecialPath");
...
}
}
I think you could use extension function, something like this
public static string ConfigToSomeThing(this IConfiguration config, int value)
{
return config[value.ToString()] ?? "";
}
Then any place , just injection IConfiguration and use extension method
_systemConfiguration.ConfigToSomeThing(123);
I just created below class:
/// <summary>
///
/// </summary>
public static class ConfigurationManager
{
/// <summary>
///
/// </summary>
public sealed class ConfigurationManagerAppSettings
{
/// <summary>
///
/// </summary>
internal ConfigurationManagerAppSettings() { }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string this[string key] => (TheConfiguration ?? throw new Exception("Set ConfigurationManager.TheConfiguration in Startup.cs")).GetSection($"AppSettings:{key}").Value;
}
/// <summary>
///
/// </summary>
public static IConfiguration? TheConfiguration { get; set; }
/// <summary>
///
/// </summary>
public static readonly ConfigurationManagerAppSettings AppSettings = new ConfigurationManagerAppSettings();
}
and below is my code:
public class Startup
{
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
ConfigurationManager.TheConfiguration = Configuration;
I've used this approach and it seems to work well. In your static class, add a public IConfiguration property.
namespace MyNamespace
{
public static class Config
{
public static IConfiguration Configuration { get; set; }
public string Username => Configuration["Username"];
public string Password => Configuration["Password"];
}
}
In Startup.cs constructor, use dependency injection to get the configuration, and then assign it to the public member of your static class.
public class Startup
{
public Startup(IConfiguration configuration)
{
MyNamespace.Config.Configuration = configuration;
}
// The rest of the startup code...
}
I was getting same issue and I wanted to access app setting in static class so I put this solution. Write this below code in static class in my code class name was EncryptionUtility
private static string _saltKey = string.Empty;
private static IConfiguration configuration;
public static void AppSettingsConfigure(IConfiguration _config)
{
configuration = _config;
_saltKey = Convert.ToString(configuration["Security:EncyptPassword"]);
}
Call Appsettingconfiure from the program.cs file. Here, EncryptionUtility is static class or you can only write static method as your requirement. I had put this line above app.Run();
EncryptionUtility.AppSettingsConfigure(app.Services.GetRequiredService<IConfiguration>());
appsettings.json :
{
"Security": {
"EncyptPassword": "Password"
}
}
Here is a way to obtain the configuration values from a NET.Core page without having to reference these statically but then still being able to pass them to other static functions called from the non-static class.
At the top of your non-static class add this:
private readonly IConfiguration _configuration;
Then in the constructor function bring in the existing configuration as input to the function:
IConfiguration configuration
Then assign the configuration to your read only variable inside the constructor function:
_configuration = configuration;
Here is an example of what it should look like:
public class IndexModel : PageModel
{
private readonly IConfiguration _configuration;
public IndexModel(IConfiguration configuration)
{
_configuration = configuration;
}
}
After this you can reference the configuration in any function in the class by referencing _configuration and can even then pass this on to other static functions that you call from other classes:
public async Task OnGetAsync()
{
AnotherClass.SomeFunction(_configuration);
}
Then in the called static class I can make use of the configuration values:
public static string SomeFunction(IConfiguration configuration)
{
string SomeValue = configuration.GetSection("SomeSectionOfConfig")["SomeValue"];
}
I have a class that calls some stored procedures for viewing and amending data and passes parameter values from appsettings.json using this approach.
Consider using the instructions here for ASP.NET Core Configuration.
You can create a class to store your configuration settings and then access the values, something like this:
_config.UserName
In Startup - ConfigureServices:
services.Configure<Config>(Configuration.GetSections("General"));
Then just inject your object wherever you need as:
IOptions<Config> config
The IConfiguration is Injectable anywhere within the Project. But in the case of static class, the option I am using and maybe only approach...
var Configuration = new ConfigurationBuilder()
.AddUserSecrets<Startup>()
.Build();
And, you can add required section, such in this code block above, I added 'UserSecrets'.

Implement OAuth with ASP.NET WebAPI

Hello Friends I would like to ask you that can any one have an example to integrate oAuth in ASP.Net web api with out integrating any packages or Entity framework??i search it a lot but find a various way using nuget packages and other packages but i need the way using simple third party calls because i need this authorization in .net as well as java api's. Can any one help me out in this.
Thanks in advance...
Yes you can do this, i implemented this in my web api using oAuth in web api 2 project.
First, have an asp.net project with oauth is configured since we will take cooy some files into web api project.
Here is the steps:
1) In the web api, add a new class file called "IdentityConfig.cs".
This class will have: ApplicationUser, ApplicationUserManager, ApplicationSignInManager and ApplicationDbContext classes.
2) Make sure that these classes above is under your api namespace so it is accessible through all your controllers.
// Configure the application user manager which is used in this api.
public class ApplicationUser : IdentityUser
{
#region custom properties
public string Name { get; set; }
public int? ZipCode { get; set; }
public long? CountryId { get; set; }
public bool IsDeleted { get; set; }
public bool EmailConfirmed { get; set; }
public DateTime CreatedDate { get; set; }
public long UserId { get; set; }
#endregion
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = true,
RequireUppercase = false,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
//manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
// Configure the application sign-in manager which is used in this api.
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
: base(userManager, authenticationManager)
{
}
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DBCONNECTIONKEY", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
Note: DBCONNECTIONKEY is the key for the connection string in web.config
3) Add Startup.cs file to the root of your web api. copy the logic from the existing one you have in asp.net. feel free to tweak the configuration context properties as needed in the web api project.
4) Use objects from these classes to sign in users, and manager application user objects as you have in asp.net web app.
That's all :)
Hope this helps.

Property injection in to Web Api controller using Autofac

I'm trying to set a property on an System.Web.Http.ApiController to a value of a resolved IServerPackageRepository. The controller runs in a HttpSelfHostServer and the DependencyResolver has been set to AutofacWebApiDependencyResolver. Here is the code from the Autofac.Module.Load method
...
builder.RegisterType<ServerPackageRepository>()
.As<IServerPackageRepository>()
.SingleInstance()
.WithParameter("path", this.StoragePath);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
.PropertiesAutowired();
The ApiController controller itself has a property of type
public IServerPackageRepository Repository { get; set; }
but is never resolved.
I am trying to do it this way because ApiController won't take nothing but default constructors. Any suggestions on how to do this the correct way using Autofac?
If the ApiController is only using the default constructor is sounds like the dependency resolver is not being called and may not be registered with Web API correctly. Here is a working example of self-hosting with constructor injection.
The dependency (in this case a simple logger):
public interface ILogger
{
void Log(string text);
}
public class Logger : ILogger
{
public void Log(string text)
{
Debug.WriteLine(text);
}
}
A simple controller with a dependency on the logger:
public class ValuesController : ApiController
{
readonly ILogger _logger;
public ValuesController(ILogger logger)
{
_logger = logger;
}
// GET api/values
public IEnumerable<string> Get()
{
_logger.Log("GET api/values");
return new string[] { "value1", "value2" };
}
}
The console application:
class Program
{
static void Main(string[] args)
{
var configuration = new HttpSelfHostConfiguration("http://localhost:8080");
configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var builder = new ContainerBuilder();
// Register API controllers using assembly scanning.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register API controller dependencies.
builder.Register<ILogger>(c => new Logger()).SingleInstance();
var container = builder.Build();
// Set the dependency resolver implementation.
var resolver = new AutofacWebApiDependencyResolver(container);
configuration.DependencyResolver = resolver;
// Open the HTTP server and listen for requests.
using (var server = new HttpSelfHostServer(configuration))
{
server.OpenAsync().Wait();
Console.WriteLine("Hosting at http://localhost:8080/{controller}");
Console.ReadLine();
}
}
}
Hit the controller action using:
http://localhost:8080/api/values
Please test this out and let me know if you have any problems.
Not sure if this is what you want but you can create your own base controller and inject the IServerPackageRepository into it.
public class MyApiController : ApiController {
public IServerPackageRepository ServerPackageRepository { get; set; }
public MyApiController(IServerPackageRepository serverPackageRepository) {
ServerPackageRepository = serverPackageRepository;
}
}
Then, use this as your base controller:
public class ProductsController : MyApiController {
public ProductsController(IServerPackageRepository serverPackageRepository)
: base(serverPackageRepository) {
}
public IEnumerable<Product> Get() {
ServerPackageRepository.DoWork();
//...
}
}
An alternative would be to directly wire your dependency to the property like so:
var repo = new ServerPackageRepository(path: this.StoragePath);
builder.RegisterInstance(repo)
.SingleInstance();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
.WithProperty("Repository", repo)
.PropertiesAutowired();

Resources