Has anyone tried using IdentityManager with vNext?
I'm having problems with the app.UseIdentityManager(IdentityManagerOptions) extension method.
It doesn't exist.
So I tried using the extension method made for UseIdentityServer (found here) by changing all the server related aspects to manager.
When I do that, I get the System.NullReferenceException in line 43.
Any kind of advice on how to go about with the extension method will be really appreciated
I am using ASPNET 5 beta6 and I got this to work.
Try using this updated IApplicationBuilder extension found in the Samples repo on dev branch. Repurpose the method to accept IdentityManagerOptions rather than IdentityServerOptions and edit the builder to UseIdentityManager
In short here is what my extension method looks like
public static class IApplicationBuilderExtensions
{
public static void UseIdentityManager(this IApplicationBuilder app, IdentityManagerOptions options)
{
app.UseOwin(addToPipeline =>
{
addToPipeline(next =>
{
var builder = new AppBuilder();
var provider = app.ApplicationServices.GetService<IDataProtectionProvider>();
builder.Properties["security.DataProtectionProvider"] =
new DataProtectionProviderDelegate(purposes =>
{
var dataProtection = provider.CreateProtector(string.Join(",", purposes));
return new DataProtectionTuple(dataProtection.Protect, dataProtection.Unprotect);
});
builder.UseIdentityManager(options);
var appFunc =
builder.Build(typeof (Func<IDictionary<string, object>, Task>)) as
Func<IDictionary<string, object>, Task>;
return appFunc;
});
});
}
}
I'm using vNext and I've noticed that many things have changed and will continue to change.
For my own needs I've been able to get identity up and running fairly easily and there are two steps that I've had to take to get it running properly. What I've done should work for you as well.
In your StartUp.cs you will need to make sure you add the following to the ConfigureServices method:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
In addition to that you will need to configure your app to use identity and to do this you need to do the following in your Configure() method:
app.UseIdentity();
Related
I am setting up an API using .NET 5 with dependency injection for my data access; using Entity Framework code first. I need to use IDbContextFactory because some of my controllers need to use more than one DbContext instance for proper Unit of Work scope.
I'm also trying to use xUnit for integration tests and am running into difficulties getting it to use in memory database.
Here is the relevant snippet from my Startup class
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ApplicationDbContext>(
options => options.UseSqlServer("connection string")
);
//other services configured
}
And this is the xUnit Application Factory that is supposed to remove the existing DbContextFactory and replace it with the InMemory factory.
public class TestApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup: class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var contextFactory = services.SingleOrDefault(
d => d.ServiceType ==
typeof(IDbContextFactory<ApplicationDbContext>)
);
services.Remove(contextFactory);
services.AddDbContextFactory<ApplicationDbContext>(
options => options.UseInMemoryDatabase("InMemoryDbForTesting")
);
var sp = services.BuildServiceProvider();
var dbf = sp.GetRequiredService<IDbContextFactory<ApplicationDbContext>>();
var db = dbf.CreateDbContext();
db.Database.EnsureCreated();
// Pass the context to a class that will add seed data
DbSeed.InitializeDbForTests(db);
});
}
When I step through in debug, it appears to be removing the existing factory as evidenced by the count of services dropping after the services.Remove(contextFactory); line and it also seems to add the new one, again by looking at the count.
This is not throwing any errors, it's just not using the new DbContextFactory.
What am I missing here?
Thank you in advance for any help.
I figured out the issue.
When the Startup class runs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ApplicationDbContext>(
options => options.UseSqlServer("connection string")
);
//other services configured
}
It is actually adding four descriptors to the service collection:
IDbContextFactory\<ApplicationDbContext>
IDbContextFactorySource\<ApplicationDbContext>
DbContextOptions
DbContextOptions\<ApplicationDbContext>
The solution is to remove all of these in the xUnit ApplicationFactory. I was only removing one. Once I removed the other three, I could continue on to add the InMemory version of the DbContextFactory and it now correctly points to the test database.
If you have a more efficient or elegant solution, I'd be interested to know.
I need to add some code to a Blazor WASM app that run as the application is starting up. I want to make a call to an API to get some settings to use during the rest of the application's lifetime.
I have verified that the API is configured correctly and that it returns data.
I've tried adding both MainLayout.razor.cs as well as App.razor.cs in order to make the call.
Neither of these worked. However when I add the SAME code to one of my other components (below), it works fine.
public class ViewMenuModel : ComponentBase
{
[Inject] HttpClient Http { get; set; }
[Inject] AppState AppState { get; set; }
protected override async Task OnInitializedAsync()
{
Settings = await Http.GetJsonAsync<List<Settings>>("settings");
UpdateSettings(Settings);
}
protected void UpdateSettings(List<Settings> settings)
{
AppState.SetSettings(settings);
}
}
Is it possible that I'm just missing something? Is this kind of thing supposed to work from either MainLayout or App?? If so, what's the trick?
It's been some time since I asked this question initially, but I think it might be valuable for future people....
When I started, I think we were on .Net core 3.1, since then, migrating to .net 6, there's actual Microsoft documentation on how to add these types of configurations
https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/configuration?view=aspnetcore-6.0
In Program.cs
var http = new HttpClient()
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
};
builder.Services.AddScoped(sp => http);
using var response = await http.GetAsync("cars.json");
using var stream = await response.Content.ReadAsStreamAsync();
builder.Configuration.AddJsonStream(stream);
When I access an ASP.NET web api using angular from the same web site, all the first letter lowercase, even if they aren't lowercase on the server.
However, if I move the API's to a different web site and enable CORS, I will receive the JSON exactly as the properties are written on the server.
Is there some way to control this difference? It becomes a mess when I need to move an API to a different web site
The default for serializing output to JSON has changed so you may encounter this issue when migrating .Net frameworks. You can read more about the issue here or here but to resolve you can specify the DefaultContractResolver.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
}
In your Owin Startup add this line...
public class Startup
{
public void Configuration(IAppBuilder app)
{
var webApiConfiguration = ConfigureWebApi();
app.UseWebApi(webApiConfiguration);
}
private HttpConfiguration ConfigureWebApi()
{
var config = new HttpConfiguration();
// ADD THIS LINE HERE AND DONE
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.MapHttpAttributeRoutes();
return config;
}
}
JSON is case sensitive as a rule JSON keys should have matching case. Some unix servers will ignore case sensitivity but I believe windows servers enforce it.
The error is in the naming conventions in the api or code requesting/processing those keys. Best to use lowercase keys using a under_score as the seperator instead of camelCasing.
http://jsonrpc.org/historical/json-rpc-1-1-alt.html#service-procedure-and-parameter-names
ref: When is case sensitivity important in JSON requests to ASP.NET web services (ASMX)?
I very read for this problem but i can not fixed this so i think create a new question in this site.
HttpContext.Current.GetOwinContext();
i want get GetOwinContext values with above code . above code there are in my startup.cs
[assembly: OwinStartupAttribute(typeof(OwinTest.Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var c = HttpContext.Current.GetOwinContext();
}
}
and i get this error
//No owin.Environment item was found in the context
but var c = HttpContext.Current.GetOwinContext(); work for me in HomeController fine.!
I just get GetOwinContext in my startup.cs class.
thankfull
You can't do that. The OWIN context does not exist without a request, and the Startup class only runs once for the application, not for each request. Your Startup class should initialize your middleware and your application and the middleware and the application should access the OWIN context when needed.
As mentioned, what you are asking isn't possible. However, depending on your requirements, the following is possible and gives you access within the context of creating object instances. This is something I needed in order to check for whether an instance was already added else where (I have multiple startup classes in different projects).
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// Ensure we have our "main" access setup
app.CreatePerOwinContext<DataAccessor>(
(options, owinContext) =>
{
// Check that an instance hasn't already been added to
// the OwinContext in another plugin
return owinContext.Get<DataAccessor>() ?? DataAccessor.CreateInstance(options, owinContext);
}
);
}
Within the CreatePerOwinContext we have access to the OwinContext, so we can access it at the point of creating a new type. This might not help everyone as it's a little more specific to a person's needs, but is useful to know.
I'm currently trying to do something that was dead simple and straight forward in ASP.NET 4 however this ins't the case now in ASP.NET 5.
Previously to use the UrlHelper it was dead simple:
var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
However I can't for the life of me wrap my head around how to use the new UrlHelper. I'm looking at the test cases and either I'm completely daft or I'm missing something and I can't seem to figure it out. Any help here in clearing up this would be great.
Update - Post RC2
As #deebo mentioned, you no longer can get an IUrlHelper directly from DI. Instead you need to inject an IUrlHelperFactory and an IActionContextAccessor into your class and use them to get the IUrlHelper instance as in:
public MyClass(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionAccessor)
{
this.urlHelperFactory = urlHelperFactory;
this.actionAccessor = actionAccessor;
}
public void SomeMethod()
{
var urlHelper = this.urlHelperFactory.GetUrlHelper(this.actionAccessor.ActionContext);
}
You need to also register the in your startup class (IUrlHelperFactory is already registered by default):
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
Bear in mind this will only work as long as the code where you get the actionContext is running after the MVC/routing middleware! (Otherwise actionAccessor.ActionContext would be null)
I have retrieved the IUrlHelper using the IServiceProvider in HttpContext.RequestServices.
Usually you will have an HttpContext property at hand:
In a controller action method you can do:
var urlHelper = this.Context.RequestServices.GetRequiredService<IUrlHelper>();
ViewBag.Url = urlHelper.Action("Contact", "Home", new { foo = 1 });
In a filter you can do:
public void OnActionExecuted(ActionExecutedContext context)
{
var urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelper>();
var actionUrl = urlHelper.Action("Contact", "Home", new { foo = 1 });
//use actionUrl ...
}
Another option would be taking advantage of the built-in dependency injection, for example your controller could have a constructor like the following one and at runtime an IUrlHelper instance will be provided:
private IUrlHelper _urlHelper;
public HomeController(IUrlHelper urlHelper)
{
_urlHelper = urlHelper;
}
Thought I would share for the upcoming RC2 since the current answer won't work anymore then.
From RC 2 you will need to explicitly register IActionContextAccessor and IUrlHelperFactory
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>();
Then use the DI/service locator:
public EmailTagHelper(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
{
_urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);
}
I blogged about it here with regard to TagHelpers: http://devonburriss.me/asp-net-5-tips-urlhelper
In Startup.cs
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>();
services.AddScoped(it => it.GetService<IUrlHelperFactory>()
.GetUrlHelper(it.GetService<IActionContextAccessor>().ActionContext));
Alternatively
PM> Install-Package AspNetCore.IServiceCollection.AddIUrlHelper
In Startup.cs
services.AddUrlHelper();
If you just need the UrlHelper.Link method like I did, you don't even need the UrlHelper any more, just use Url.Link
A shorter version without constructing special Factory class
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
.AddScoped<IUrlHelper>(sp => new UrlHelper(sp.GetRequiredService<IActionContextAccessor>().ActionContext));