I was using the following code to add roles of the user.
Roles.AddUserToRole(model.Email, "COMPANYVIP");
and then i got this error:
The Role Manager feature has not been enabled
after some research i found out that we have to add the following connection string in web.config
<configuration>
<system.web>
<roleManager enabled="true" />
</system.web>
</configuration>
adding this eliminated my first error but now i get this error:
A network-related or instance-specific error occurred while establishing a connection to SQL Server
what should i do now?
Remove your change in web.config and in Startup.Auth add the following reference to ConfigureAuth:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
// Add this reference to RoleManager (without changing any other items)
// Make sure it is added below ApplicationDbContext.Create
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
}
Then in your Controller, make sure it includes this in the constructor:
public class YourController : Controller
{
// Add this
private ApplicationRoleManager _roleManager;
// Add roleManager
public YourController(ApplicationRoleManager roleManager)
{
// Add this
RoleManager = roleManager;
}
public ApplicationRoleManager RoleManager {
get {
return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
}
private set {
_roleManager = value;
}
}
}
and also include this in the Controller's Dispose (if you have it):
protected override void Dispose(bool disposing)
{
if (disposing)
{
// include this
if (_roleManager != null)
{
_roleManager.Dispose();
_roleManager = null;
}
}
base.Dispose(disposing);
}
You may also need to add this code to IdentityConfig (in the App_Start folder if you're using the template):
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{ }
public static ApplicationRoleManager Create(
IdentityFactoryOptions<ApplicationRoleManager> options,
IOwinContext context)
{
var manager = new ApplicationRoleManager(
new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
return manager;
}
}
You should now be able to use the RoleManager in the Controller.
Related
I am using asp.net mvc applicaiton and I am new about cross cutting concers. So I need to know where can I use my logger code following example.
I have an interface that logs erros. I am implementing this interface on my code.
public interface ILogger { void Log(Exception exception); }
So I have Controller, ProductService, ProductRepository classes.
public interface ProductController: ApiController{
public IHttpActionResult Get(){
try {
productService.GetProducts();
}catch(Exception e){
logger.Log(e); // 1-Should I use logging in here?
}
}
}
Product service;
public class ProductService{
public IEnumerable<Product> GetProducts(){
try {
productRepository.GetAll();
}catch(Exception e){
logger.Log(e); // 2-Should I use logging in here?
}
}
}
In repository.
public class ProductRepository{
public IEnumerable<Product> GetAll(){
try {
}catch(Exception e){
logger.Log(e); // 3-Should I use logging in here?
}
}
}
I could not determine where can I use logging code. Or add logging in everywhere.
You can implement custom exception filter.
public class LogExceptionAttribute : ExceptionFilterAttribute
{
public ILogger logger { get; set; }
public LogExceptionAttribute(ILogger logger)
{
this.logger = logger;
}
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exception = actionExecutedContext.Exception;
logger.Log(actionExecutedContext.Exception);
// You could also send client a message about exception.
actionExecutedContext.Response =
actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError, exception.Message);
}
}
Then register it on global level.
GlobalConfiguration.Configuration.Filters.Add(new LogExceptionAttribute(Logger));
This filter would be called for any unhandled exception thrown from controller method.
I am working on the ForgotPassword section of my site. When I test it I have a breakpoint in the function and I can see that this line of code is returning false:
(await UserManager.IsEmailConfirmedAsync(user.Id)))
I have verified that EmailConfirmed field in the AspNetUsers table is set to True. Why would this still be returning false?
Here is the first part of the Account Controller where it initializes the UserManager:
[Authorize]
public class AccountController : Controller
{
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
{
UserManager = userManager;
SignInManager = signInManager;
}
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
}
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
Found the requested Owin string in my Startup.Auth.cs class:
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
You are likely pointing to the wrong database. The default templates for an MVC project with Identity will have code like this in the context:
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
This is then used by OwinContext as the method to create your context, and as such means that it will take the connection string from your web.config file called DefaultConnection. So you have 2 choices:
Fix the connection string to point to the correct database.
<add name="DefaultConnection"
connectionString="correct details here"
providerName="System.Data.SqlClient" />
Change the create method to return the context with a specific connection string:
public static ApplicationDbContext Create()
{
return new ApplicationDbContext("NameOfConnectionStringHere");
}
It seems await UserManager.IsEmailConfirmedAsync(user.Id)) always returns false when EmailConfirmed is set to False in AspNetUsers SQL table.
i have a .NET 3.5 solution with an asp.net(web site) project with fluentnhibernate and it's test project(class library project).i've referenced the asp.net project in the test project and with all fluentnhibernate/nhibenate dlls.
What i fail to comprehend is that, on a run of a webform (hit from browser) let's say Test.aspx, building of schema is successfull and i could see the tables in my database.
here is the method i call on Test.aspx.cs
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ISession session = SessionManager.Instance.OpenSession();
SessionManager.BuildSchema(session);
}
}
i happen to use the same method in CanGenerateSchema method of my test class and it always fails
[TestFixture]
public class CanGenerateSchemaTestSuite
{
[Test]
public void CanGenarateSchema()
{
ISession session = SessionManager.Instance.OpenSession();
SessionManager.BuildSchema(session);
}
}
here is the SessionManager i use :
public sealed class SessionManager
{
private readonly ISessionFactory _sessionFactory;
public static ISessionFactory SessionFactory
{
get { return Instance._sessionFactory; }
}
private ISessionFactory GetSessionFactory()
{
return _sessionFactory;
}
public static SessionManager Instance
{
get { return NestedSessionManager._sessionManager; }
}
public ISession OpenSession()
{
return Instance.GetSessionFactory().OpenSession();
}
private static Configuration SaveConfigs;
private SessionManager()
{
try
{
if (_sessionFactory == null)
{
//from the debugging the code breaks from here when trying to get connectionstring.
string constring = ConfigurationManager.AppSettings["localdb"].ToString();
FluentConfiguration configuration = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(constring))
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<myproject.model.Request>();
m.FluentMappings.AddFromAssemblyOf<myproject.model.Route>();
})
.ExposeConfiguration((x) =>
{
SaveConfigs = x;
x.SetProperty("current_session_context_class", "thread_static");
});
_sessionFactory = configuration.BuildSessionFactory();
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
}
public static void BuildSchema(ISession session)
{
var export = new SchemaExport(SaveConfigs);
export.Execute(false,true,false,session.Connection,null);
}
class NestedSessionManager
{
internal static readonly SessionManager _sessionManager = new SessionManager();
}
}
So from my comment the NullReferenceException happens when accessing the connectionstring. I don't have the explanation on why that happens.I'm sure it's some kind of gotchas, i can't get over it.I would be very grateful if anyone could give me a hand here.thanks for reading.
ConfigurationManager.AppSettings["localdb"] from Test.aspx would be pulling from your web.config file on a web project.
That file wouldn't be accessible to your test project (I'm assuming your tests are in a separate project from your web site). You should be able to get around this by adding an app.config file into your test project with the correct localdb settings or rather than using a configuration string, use FluentNHibernate's fluent builder.
Example app.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="localdb" value="yourconnectionstring" />
</appSettings>
</configuration>
If the value returned by ConfigurationManager.AppSettings["localdb"] is null then the .ToString() call will cause the NullReferenceException.
Ensure the "localdb" setting exists.
Is it possible to iterate the OutputCache keys? I know you can remove them individually via HttpResponse.RemoveOutputCacheItem(), but is there a way I can iterate all the keys to see what's in the collection?
I searched through Object Viewer, but didn't see anything.
Worst case, I can maintain my own index. Since I'm doing everything by VaryByCustom, they get "fed" through a method in global.asax. It just strikes me that there has to be a more elegant way of doing this.
If you're using ASP.NET 4.0 you could do this by writing your own OutputCacheProvider. That would give you the ability to store the keys at the point that the item is cached:
namespace StackOverflowOutputCacheProvider
{
public class SOOutputCacheProvider: OutputCacheProvider
{
public override object Add(string key, object entry, DateTime utcExpiry)
{
// Do something here to store the key
// Persist the entry object in a persistence layer somewhere e.g. in-memory cache, database, file system
return entry;
}
...
}
}
You'd then be able to read the keys out from wherever you've stored them.
This can be accomplished by inheriting MemoryCache and exposing the enumerator via a custom OutputCacheProvider implementation. Keep in mind that the enumerator locks the cache. Enumerating over the cache should be executed infrequently.
namespace Caching
{
internal class MemoryCacheInternal : System.Runtime.Caching.MemoryCache
{
public MemoryCacheInternal(string name, System.Collections.Specialized.NameValueCollection config = null) : base(name, config)
{
}
public System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string, object>> Enumerator()
{
return base.GetEnumerator();
}
}
}
Implement a custom OutputCacheProvider
using System.Web.Caching;
using System.Collections.Generic;
namespace Caching
{
public class EnumerableMemoryOutputCacheProvider : OutputCacheProvider, IEnumerable<KeyValuePair<string, object>>, IDisposable
{
private static readonly MemoryCacheInternal _cache = new MemoryCacheInternal("EnumerableMemoryOutputCache");
public override object Add(string key, object entry, System.DateTime utcExpiry)
{
return _cache.AddOrGetExisting(key, entry, UtcDateTimeOffset(utcExpiry));
}
public override object Get(string key)
{
return _cache.Get(key);
}
public override void Remove(string key)
{
_cache.Remove(key);
}
public override void Set(string key, object entry, System.DateTime utcExpiry)
{
_cache.Set(key, entry, UtcDateTimeOffset(utcExpiry));
}
public IEnumerator<KeyValuePair<string,object>> GetEnumerator()
{
return _cache.Enumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _cache.Enumerator();
}
private DateTimeOffset UtcDateTimeOffset(System.DateTime utcExpiry)
{
DateTimeOffset dtOffset = default(DateTimeOffset);
if ((utcExpiry.Kind == DateTimeKind.Unspecified)) {
dtOffset = DateTime.SpecifyKind(utcExpiry, DateTimeKind.Utc);
} else {
dtOffset = utcExpiry;
}
return dtOffset;
}
#region "IDisposable Support"
// To detect redundant calls
private bool disposedValue;
// IDisposable
protected virtual void Dispose(bool disposing)
{
if (!this.disposedValue) {
if (disposing) {
_cache.Dispose();
}
}
this.disposedValue = true;
}
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
Configure the custom OutputCacheProvider
<system.web>
<caching>
<outputCache defaultProvider="EnumerableMemoryCache">
<providers>
<add name="EnumerableMemoryCache"
type="Caching.EnumerableMemoryOutputCacheProvider, MyAssemblyName"/>
</providers>
</outputCache>
<outputCacheSettings>
<outputCacheProfiles>
<add name="ContentAllParameters" enabled="false" duration="14400" location="Any" varyByParam="*"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
Enumerate over the cache, in this case removing cache items.
OutputCacheProvider provider = OutputCache.Providers[OutputCache.DefaultProviderName];
if (provider == null) return;
IEnumerable<KeyValuePair<string, object>> keyValuePairs = provider as IEnumerable<KeyValuePair<string, object>>;
if (keyValuePairs == null) return;
foreach (var keyValuePair in keyValuePairs)
{
provider.Remove(keyValuePair.Key);
}
I have use this
http://www.codeproject.com/KB/session/exploresessionandcache.aspx
to view the cache and the session data. I only have to say that show only one pools data. If you have more pools, then you just see the one you are on it.
Guys, is it possible to get physical path to asp.net mvc 2 application inside Global.asax methods?
UPD: sorry, i forget to say, that I need to get that path in Ninject IoC container configuration.
This is a sketch of what i'm having now:
public class MvcApplication : System.Web.HttpApplication
{
...
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(typeof(IOCControllerFactory));
}
}
public class IOCControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public IOCControllerFactory()
{
kernel = new StandardKernel(new NanocrmContainer());
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
var controller = kernel.TryGet(controllerType) as IController;
if (controller == null)
return base.GetControllerInstance(requestContext, controllerType);
var standartController = controller as Controller;
return standartController;
}
class NanocrmContainer : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<IFileService>().To<BusinessLogic.Services.FileService>().InRequestScope().WithConstructorArgument("temp", "Temp").WithConstructorArgument("docs", "Documents"); // Temp and Documents should be replaced with corresponding paths
}
}
}
You're looking for the HttpRuntime.AppDomainAppPath property.